Are user defined deduction guides involving template template parameter as a template for guidance standard compliant
Asked Answered
B

1

12

Background

Yesterday I asked a question about the guarantees of deduction guides usage in case of template template parameters. I was really surprised when Barry changed his answer to the confirmation of standard complianceness of the code. My surprise doesn't actually come from the fact deduction guides can be applied for template template parameters, but more from the standard part which conforms this compliance, namely [temp.param]/3:

A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared without template) or template-name (if declared with template) in the scope of the template declaration.

This plus [temp.deduct.guide]/1 and the rule for simple-template-id would allow one to create a generic deduction guide accepting any template.

Example

#include <string>

template <class T>
struct Foo {
   Foo(T) { }
};

template <template <class> class TT>
TT(const char *) -> TT<std::string>;

int main() {
    Foo foo("abc");
}

The question

The code causes gcc to crash with internal error and results in compilation error in clang. To be straight, I am not saying the code should be actually allowed in C++ but think the current wording does make it conformant. Am I missing some important rule that disallows the code?

Batholith answered 7/10, 2017 at 18:59 Comment(4)
Oh man. I hope this isn't allowed :)Plafker
@Plafker yep, this would be very annoying :) It could be explicitly prohibited to minimize influence on the other parts of standard...Batholith
From Richard Smith, lol: "Hah, we never intended that to be valid, but I don't see any rule in the current wording that prohibits it." This'll end up being a core language defect.Plafker
@Plafker see my answer belowPhina
P
2

Your example

At the risk of being wrong, I would cite a now-deleted answer

If I'm not mistaken this goes afoul of [temp.deduct.guide]p3:

The simple-template-id shall name a class template specialization.

TT<std::string> does not name a class template specialization, and your code is ill-formed.

There is also this in [temp.spec]p4:

A specialization is a class, function, or class member that is either instantiated or explicitly specialized.

TT is a template type-parameter technically. And the construct TT<std::string> is a type-dependent type-name. If the deduction-guide would be an actual function template and we would instantiate it, TT<std::string> could be instantiated as class-name that referred to a class template specialization. It could also refer to int if TT is instantiated to refer to a suitably defined alias-template. But as-is, in the deduction-guide declaration, it does not yet name a class template specialization.

There is a rule at [temp.res]p8.5.5 that says

Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated.

So, can a specialization of a deduction-guide happen at all? I argue with no. First of all, it's not a "templated entity" (c.f. [temp]p8) that could be instantiated. What is specialized in class template argument deduction is a set of templates that are formed based on the deduction guides, but not the guides themselfs. See [over.match.class.deduct]p1.4

[...] For each deduction-guide, a function or function template with the following properties [is formed]: [...]

It's those function templates that are specialized further in the process of overload-resolution. The deduction guides themselfs are never specialized, therefore, we can generate a diagnostic message for violation of the rule that the simple-template-id in the deduction-guide does not name a class template specialization.

Naming by an alias template (Richard's example)

Richard gave a different example

template<typename T> class X { T t; };
template<typename T> using Y = X<T*>;
template<typename T> Y(T) -> Y<T>;

In this case, it's more complicated and I think this might be allowed by the wording, as Y<T> is actually a class template specialization. You can now argue about whether it actually names the specialization or merely denotes it, after rewriting rules are applied. The fact that it could allow for arguments would appear to be enough to warrant a defect report, IMO.

Phina answered 12/11, 2017 at 14:51 Comment(3)
I don't know how you do it but you always make my mind blown ;) Let me analyze your answer a bit more to be sure if I really understand it :)Batholith
@Batholith my argument is that it does not name a class template specialization. That it's dependent is noteworthy. But it's not by itself the reason. In Foo<T>, the name Foo<T> names an (unknown) specialization of the class template Foo, so it names a class template specialization. But in TT<std::string>, it names a yet unknown type (hence my note that it's a dependent type). At definition time of the deduction guide, the name therefore doesn't name a class template specialization.Phina
yes - sorry I re-read your (as I said mind-blowing) answer again and I think I see your point about the dependent type-name... I haven't seen it before as TT (AFAIK) can't really be deduced if it is an alias... I think this could be the answer and maybe there is no language defect here after all...Batholith

© 2022 - 2024 — McMap. All rights reserved.