我一直在尝试编译一个项目(使用gcc / g ++很好),并且在模板调用中卡住了clang和编译。 我试图创建最简单的类似代码,显示相同的错误消息。这是:
#include <vector>
#include <utility>
#include <iostream>
using namespace std;
int A( double in )
{
return 1;
}
int A( int in )
{
return 1;
}
template<class M, class T>
M test(T input, M (fun) (T) )
{
return fun( input );
}
int main( int argc, const char *argv[] )
{
cout << test( (int) 1, A ) << test( (double) 1.2, A ) << endl;
return 0;
}
来自clang的错误(当然会出现两次):
error: no matching function for call to 'test'
candidate template ignored: couldn't infer template argument 'M'
Gcc不抱怨。 请注意M是返回类型,并且始终为“int”。
有人知道哪个是对的,为什么?
由于
答案 0 :(得分:8)
g ++错了。来自C ++ 11 [temp.deduct.type] p5:
未推断的背景是:[...] - 无法进行参数推导的函数参数,因为关联的函数参数是一组重载函数,并且[...]多个函数与函数参数类型匹配
此判断不考虑可能在其他地方推断的模板参数,因此T
必须推导为int
的事实与此无关。这使得整个参数M (fun)(T)
成为非推导的上下文。因此,正如Clang声称的那样,M
无法推断出来。
T
= int
'推论。颠倒函数参数的顺序会导致g ++拒绝代码:
int A(double);
int A(int);
template<class M, class T>
M test(M (fun) (T), T input) {
return fun( input );
}
int main( int argc, const char *argv[]) {
test(A, 1);
test(A, 1.2);
}
答案 1 :(得分:2)
我之前的回答(现已删除)错了。 Clang错了。
编译器应该能够推导出类型M
,因为函数参数是M(fun)(T)
。请注意,函数指针参数列表中没有M
,因此这对应于14.8.2.5中的T()
(C ++ 11)/ T(*)()
(C ++ 93):
其中
(T)
表示参数类型列表,其中至少一个参数类型包含T
,()
表示 parameter-type-list ,其中没有参数类型包含T
。