[英]Template argument deduction for an argument of a function type
Consider the following program.考虑以下程序。
#include <iostream>
template <typename T>
void f( void ( *fn )( T ) )
{
fn( 42 );
}
void g( int x )
{
std::cout << "g( " << x << " );\n";
}
int main()
{
f( g );
}
The program compiles successfully and its output is程序编译成功,输出为
g( 42 );
Now let's rename the non-template function g
to f
.现在让我们将非模板函数
g
重命名为f
。
#include <iostream>
template <typename T>
void f( void ( *fn )( T ) )
{
fn( 42 );
}
void f( int x )
{
std::cout << "f( " << x << " );\n";
}
int main()
{
f( f );
}
Now the program is not compiled by gcc HEAD 10.0.0 20200 and clang HEAD 10.0.0 but compiled successfully by Visual C++ 2019..现在该程序不是由 gcc HEAD 10.0.0 20200 和 clang HEAD 10.0.0 编译的,而是由 Visual C++ 2019 编译成功..
For example the compiler gcc issues the following set of messages.例如,编译器 gcc 会发出以下一组消息。
prog.cc: In function 'int main()':
prog.cc:22:10: error: no matching function for call to 'f(<unresolved overloaded function type>)'
22 | f( f );
| ^
prog.cc:4:6: note: candidate: 'template<class T> void f(void (*)(T))'
4 | void f( void ( *fn )( T ) )
| ^
prog.cc:4:6: note: template argument deduction/substitution failed:
prog.cc:22:10: note: couldn't deduce template parameter 'T'
22 | f( f );
| ^
prog.cc:14:6: note: candidate: 'void f(int)'
14 | void f( int x )
| ^
prog.cc:14:13: note: no known conversion for argument 1 from '<unresolved overloaded function type>' to 'int'
14 | void f( int x )
| ~~~~^
So a question arises: should the code be compiled and what is the reason that the code is not compiled by gcc and clang?那么问题来了:代码要不要编译,gcc和clang没有编译的原因是什么?
It would seem to me that gcc and clang are correct.在我看来 gcc 和 clang 是正确的。 This should not compile.
这不应该编译。 The function parameter from which you'd like
T
to be deduced becomes a non-deduced context here the moment the argument supplied is an overload set that contains a function template [temp.deduct.type]/5.5 :当提供的参数是包含函数模板[temp.deduct.type]/5.5的重载集时,您希望从中推导出
T
的函数参数成为非推导上下文:
The non-deduced contexts are:
非推导的上下文是:
- […]
[…]
A function parameter for which argument deduction cannot be done because the associated function argument is a function, or a set of overloaded functions ([over.over]), and one or more of the following apply:
由于关联的函数参数是一个函数或一组重载函数 ([over.over]),因此无法对其进行参数推导的函数参数,并且以下一项或多项适用:
- […]
[…]
- the set of functions supplied as an argument contains one or more function templates.
作为参数提供的一组函数包含一个或多个函数模板。
- […]
[…]
Thus, T
cannot be deduced and the other overload is not viable due to there being no conversion;因此,无法推导出
T
并且由于没有转换,另一个重载是不可行的; exactly what gcc says…正是 gcc 所说的......
These are two overloaded functions and non-template function is should be selected compare to templated function, so f(int x) was selected hence passing a function as an argument in the function which int must be passed is impossible .这是两个重载函数,与模板化函数相比,应该选择非模板函数,因此选择了 f(int x),因此在必须传递 int 的函数中将函数作为参数传递是不可能的。 and the below should work.
下面应该工作。 Thanks
谢谢
void f( void ( *fn )( int ) ){
fn( 42 );
}
void f( int x ){
std::cout << "f( " << x << " );\n";
}
int main(){
f( f );
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.