看看这个(简化的)例子:
int foo(int) { return 0;}
double foo(double) { return 0.0; }
template <class T>
enable_if<is_integral<T>::value>
bar(T(*f)(T)) {}
int main()
{
bar(foo);
return 0;
}
我的期望是编译器将首先尝试为每个重载实例化模板,这将导致第二次重载失败(SFINAE),因此候选集合中只剩下void bar(int(*f)(int)
使用foo
的第一个重载来解决。这不是发生的事情。它失败了这样的事情:
no matching function for call to ‘bar(<unresolved overloaded function type>)’
couldn't deduce template parameter ‘T’
有没有办法实现这样的目标?
答案 0 :(得分:2)
C ++的类型演绎非常简单。子句[temp.deduct.call]/6.2和[over.over]/1描述了重载名称可用作参数的方式。
在您的示例中,两个推论都会成功(到T=int
和T=double
)并且一个替换会失败。但这种语言只需要一次扣除即可。
你问过如何实现它。以下是一些选项:
#2的例子:
tempate<class T> struct integral_wrapper { T t; }
integral_wrapper<int> foo(int);
double foo(double);
template<class T>
void bar(integral_wrapper<T> foo(T));
#3的例子:
template<class T>
void bar(T (*f)(T), T);
bar(foo, 0);
#4的例子:
struct foo_t
{
int operator()(int);
double operator()(double);
} foo;
template<class F>
void bar(F);
bar(foo);
请注意,通用lambda可能是#4的另一种方法。
根据您的使用情况,其中一些可能比其他更具吸引力。方法#4在将参数传递给STL算法时特别有用。