函数参数的隐式实例化

aer*_*sis 8 c++ c++17

我试图弄清楚函数参数的隐式实例化是如何工作的.由于某些原因,在第一个示例中,bar()调用将其解释{12,41}为初始化列表.如果我改变了foo对签名auto foo(std::pair<int,int> bar){12,41}隐式转换的std::pair<int,int>.

例如

template<typename T, typename U>
auto foo(std::pair<T,U> arg) { return arg; }
auto bar()                   { return foo({12,41}); }
Run Code Online (Sandbox Code Playgroud)

失败并出错:

<source>: In function 'auto bar()':
104 : <source>:104:50: error: no matching function for call to 'foo(<brace-enclosed initializer list>)'
 auto bar()                   { return foo({12,41}); }
                                                  ^
103 : <source>:103:6: note: candidate: 'template<class T, class U> auto foo(std::pair<_T1, _T2>)'
 auto foo(std::pair<T,U> arg) { return arg; }
      ^~~
103 : <source>:103:6: note:   template argument deduction/substitution failed:
104 : <source>:104:50: note:   couldn't deduce template parameter 'T'
 auto bar()                   { return foo({12,41}); }
                                                  ^
Run Code Online (Sandbox Code Playgroud)

auto foo(std::pair<int,int> arg) { return arg; }
auto bar()                       { return foo({12,41}); }
Run Code Online (Sandbox Code Playgroud)

作品.有人会关心详细说明原因吗?

Nir*_*man 13

出于通常的原因:隐式转换往往不会以模板化函数的相同方式(或根本不会)发生.在你的第二个例子中:

auto foo(std::pair<int,int> arg) { return arg; }
auto works()                     { return foo({12,41}); }
Run Code Online (Sandbox Code Playgroud)

foo是一个函数,而不是一个函数模板.std::pair有一个非显式的两个参数构造函数:http://en.cppreference.com/w/cpp/utility/pair/pair.具有n个条目的大括号包可以隐式转换为具有n元隐式构造函数的类型.所以你从隐式转换{12,31}std::pair<int, int>.

调用函数模板时,模板推导将尝试推导模板以使参数匹配.在此过程中,无法进行全范围的隐式转换.只允许进行非常特殊的转换:http://en.cppreference.com/w/cpp/language/template_argument_deduction.基本上,CV转换,派生到基础转换,以及一些指针限定和函数指针转换.

所以:

template <class T, class U>
auto foo(std::pair<T, U> arg) { return arg; }
auto bar()                    { return foo({12,41}); }
Run Code Online (Sandbox Code Playgroud)

失败,因为在foo调用时,它会尝试将模板参数替换为foo调用参数并使参数匹配,但不能使它们足够精确地匹配.

我没有评论pair<auto, auto>语法,但情况与更明确的语法完全相同,所以我不认为这是问题的核心.

之前在SO上讨论过这个问题:使用模板进行C++隐式类型转换,因此值得阅读以获取更多信息.虽然,请注意,那里接受的答案错误地表明在匹配函数模板时只允许CV资格更改; 这不太正确(也许我会建议在那里编辑).