Function template parameter pack followed by template parameter and specialisation

Viewed 122

Can a template parameter pack used in the definition of a function template, be followed by another template parameter, when that parameter is only given its required default value, in the definition; and not the declaration? Consider the following example:

template <typename ...Ts, typename T>
auto sz(Ts...);

template <typename ...Ts, typename T = int>
auto sz(Ts...) { return sizeof...(Ts); }

I find that GCC and Clang disagree on this (GCC gives a compilation error).

1 Answers

-- EDIT -- corrected after an initial misundertanding.

I suppose g++ is right and clang++ is wrong.

According the C++17 standard, 17.1.11,

template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list (11.3.5) of the function template or has a default argument (17.8.2).

So a template parameter, with a default value, should be accepted after a variadic pack.

The problem is: we can set the the template default values only in function declarations or also in function definitions (when distinct from function declarations)?

In fact, you can simplify your problem simply with

template <typename>
void foo ();

template <typename = int>
void foo ()
 { }

int main ()
 {
   foo();
 }

accepted by clang++ and rejected by g++.

This isn't completely clear to me but, in 17.1.9 I read

A default template-argument may be specified in a template declaration. A default template-argument shall not be specified in the template-parameter-list s of the definition of a member of a class template that appears outside of the member’s class. A default template-argument shall not be specified in a friend class template declaration. If a friend function template declaration specifies a default template-argument , that declaration shall be a definition and shall be the only declaration of the function template in the translation unit

This fragment explicit that "A default template-argument may be specified in a template declaration". Non in "definition".

Exclude that "A default template-argument shall not be specified in the template-parameter-list s of the definition of a member of a class template that appears outside of the member’s class", so I initially concluded that a template generic function can specifies default template-argument in "definition" but this part is about a "class template", so the template-argument are about the class, not about the member.

As pointed by sigma (thanks!) in 17.1.10 we can read

The set of default template-argument s available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are

Again: "declarations" and no "definition".

So I suppose clang++ is wrong and g++ is right.

Related