Why is template parameter pack used in a function argument type as its template argument list not able to be explicit specified

gnaggnoyil :

I have the following piece of code:

template <typename, typename>
struct AAA{};

template<typename ...Args>
void f(AAA<Args...> *) {}

int main() {
    f<int, int>(nullptr);
}

This code results in a compile error. When compiling using g++ -std=c++1z the error shows as follows:

prog.cc: In function 'int main()':
prog.cc:8:24: error: no matching function for call to 'f<int, int>(std::nullptr_t)'
     f<int, int>(nullptr);
                        ^
prog.cc:5:6: note: candidate: template<class ... Args> void f(AAA<Args ...>*)
 void f(AAA<Args...> *) {}
      ^
prog.cc:5:6: note:   template argument deduction/substitution failed:
prog.cc:8:24: note:   mismatched types 'AAA<Args ...>*' and 'std::nullptr_t'
     f<int, int>(nullptr);

Using clang++ -std=c++1z the error is:

prog.cc:8:5: error: no matching function for call to 'f'
    f<int, int>(nullptr);
    ^~~~~~~~~~~
prog.cc:5:6: note: candidate template ignored: could not match 'AAA<int, int, Args...> *' against 'nullptr_t'
void f(AAA<Args...> *) {}
     ^
1 error generated.

I am running those above in a MSYS2 MinGW-w64 environment. My GCC version is GCC 7.1.0 and my Clang version is 4.0.0; the standard library I use both in GCC and in Clang is the libstdc++ bundled with my GCC compiler.

In my opinion, the call to function template foo has its template parameter explicitly specified thus the template parameter pack and the function argument type should already be specified. However, the error diagnostics shown above seem to suggest that the exact type of function parameter and the nullptr argument does not match, which seems to be a issue only possible when function argument deduction occurs. So my question is, why does such error occur? Is it just a compiler bug, or does the C++ standard have some rules that indicate the original code is just ill-formed?

StoryTeller - Unslander Monica :

You may think the compiler should deduce the pack as int ,int, but the C++ standard explicitly requires the behavior you observed.

[temp.arg.explicit/9]

Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments. [ Example:

template<class ... Types> void f(Types ... values);
void g() {
  f<int*, float*>(0, 0, 0);     // Types is deduced to the sequence int*, float*, int
}

— end example ]

The above means that even though some of the parameters were specified, deduction doesn't end. The parameter pack must always be expandable by argument deduction. It's as if the explicit arguments that were given are an instantiation of a template with a trailing parameter pack. When coupled with the following:

[temp.arg.explicit/3]

Trailing template arguments that can be deduced or obtained from default template-arguments may be omitted from the list of explicit template-arguments. A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments. ...

The compiler must match the un-deduced arguments to an empty pack. But it has nothing to deduce it from.

As such, your attempt to plug Args... into AAA cannot possibly match. Because the type sequence is two types with a trailing list (that the compiler cannot deduce as empty from nullptr). While AAA expects just two types.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Template function getting argument pack and initializer list

Parameter pack with default template argument

What if template argument explicitly specified to be function type

auto in function parameter list implying template argument

Why can't C++ deduce a template type argument from a function pointer prototype individually but not as a pack?

Template argument for template type parameter must be a type

C++ Sum parameter pack into a template argument

Template deduction fails with argument after parameter pack

How to specify a default argument for a template parameter pack?

Variadic template function where return type depends on template argument list

C++ template pack for function argument

Template argument deduction for an argument of a function type

template argument deduction of return type in function template

Declaring an incomplete type template parameter in place in-the argument list

type/value mismatch at argument 1 in template parameter list c++

Deduction failure of function call with explicit template argument list and [temp.arg.explicit]/3

A template function as a template argument

Template function as template argument

Explicit template instantiation for member function with boolean template argument

Function template parameter pack not at the end of the parameter list

c++ variadic templates and template template arguments: error: type/value mismatch at argument 1 in template parameter list

Template default argument loses its reference type

How to create function-template, that expands parameter-pack which doesn't represent function argument(s)?

Why does a function literal used as a default argument require a parameter type?

no instance of function template matches the argument list i dont know why

Why does comparison function type need to specified as template parameter?

Can placeholder type in non-type template parameter involve overload resolution of the function passed as a template argument?

'T' is not a valid template type argument for parameter 'T'

Determining the type of the template parameter method argument