Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
131 views
in Technique[技术] by (71.8m points)

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

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?

question from:https://stackoverflow.com/questions/45318502/why-is-template-parameter-pack-used-in-a-function-argument-type-as-its-template

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...