Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 598
W.F. Avatar asked Oct 07 '17 18:10

W.F.


People also ask

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.

What is a deduction guide?

Template deduction guides are patterns associated with a template class that tell the compiler how to translate a set of constructor arguments (and their types) into template parameters for the class. The simplest example is that of std::vector and its constructor that takes an iterator pair.


1 Answers

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.

like image 120
Johannes Schaub - litb Avatar answered Sep 21 '22 15:09

Johannes Schaub - litb