Clang“无法推断模板参数”,而gcc / g ++可以。哪个是对的?

时间:2013-07-23 10:05:15

标签: c++ templates gcc clang

我一直在尝试编译一个项目(使用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”。

有人知道哪个是对的,为什么?

由于

2 个答案:

答案 0 :(得分:8)

g ++错了。来自C ++ 11 [temp.deduct.type] p5:

  

未推断的背景是:[...]    - 无法进行参数推导的函数参数,因为关联的函数参数是一组重载函数,并且[...]多个函数与函数参数类型匹配

此判断不考虑可能在其他地方推断的模板参数,因此T必须推导为int的事实与此无关。这使得整个参数M (fun)(T)成为非推导的上下文。因此,正如Clang声称的那样,M无法推断出来。

在确定第二个参数是否是非推断的上下文时,g ++似乎错误地使用了来自第一个函数参数的'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