Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can C++17's deduced `auto` non-type `template` parameters pattern-match templates with explicit non-type parameters?

Consider this example (also available on wandbox):

template <template <auto> class>
void test() { }

template <int> 
struct X { };

Trying to instantiate test<X>() on clang++ 4.0 (trunk) results in a compilation error:

error: no matching function for call to 'test'
     test<X>();
     ^~~~~~~

note: candidate template ignored: 
      invalid explicitly-specified argument for 1st template parameter
void test() { }

My initial assumption/intuition was that test could be used to match any template having a non-type parameter.


However, the following code snippet successfully compiles:

template <template <auto> class>
void test() { }

//        vvvv
template <auto> 
struct X { };

Is this intended? Could not find anything conclusive in P0127R2.

like image 479
Vittorio Romeo Avatar asked Oct 02 '16 01:10

Vittorio Romeo


People also ask

Which parameter is allowed for non-type template?

Which parameter is legal for non-type template? Explanation: The following are legal for non-type template parameters:integral or enumeration type, Pointer to object or pointer to function, Reference to object or reference to function, Pointer to member.

Can we use non-type parameters as argument templates?

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

What is template argument deduction in C++?

Class Template Argument Deduction (CTAD) is a C++17 Core Language feature that reduces code verbosity. C++17's Standard Library also supports CTAD, so after upgrading your toolset, you can take advantage of this new feature when using STL types like std::pair and std::vector.


1 Answers

It's definitely intended. Template-template parameters can only match templates which take the same kinds of arguments. This:

template <template <auto> class>
void test() { }

can only be instantiated with a class template that can take any kind of non-type parameter. But this:

template <int> 
struct X { };

is not such a class template. X can only be instantiated with an int. It simply does not match the specification for the template template parameter, hence the error. What if test wanted to instantiate its class template with a pointer type? Or pointer to function or pointer to member? That would be impossible.

Your second attempt, with template <auto> struct X { }; does match the template-template parameter, hence is well-formed. Note also that the reverse, having test take a template <int> class parameter and passing in template <auto> struct X { }; is also well-formed as the argument is more general than the parameter.


The relevant wording is in [temp.arg.template]:

A template-argument matches a template template-parameter P when each of the template parameters in the template-parameter-list of the template-argument’s corresponding class template or alias template A matches the corresponding template parameter in the template-parameter-list of P. Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent (14.5.6.1), and for template template-parameters, each of their corresponding template-parameters matches, recursively.


Note: the equivalence wording accepts the auto - auto case and rejects the auto - int case, but also seems to reject the int - auto case (based on my reading). I'm going to try to get some clarification on it.

like image 88
Barry Avatar answered Sep 18 '22 12:09

Barry