Reputation: 13988
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 withtemplate
) 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.
#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 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?
Upvotes: 12
Views: 681
Reputation: 507065
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.
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.
Upvotes: 2