21

我一直在尝试用clang编译一个项目(使用gcc/g++很好),并且编译停留在模板调用上。我尝试创建显示相同错误消息的最简单的类似代码。这里是:

#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”。

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

谢谢

4

2 回答 2

8

g++ 是错误的。从 C++11 [temp.deduct.type]p5 开始:

非推导上下文是: [...] - 一个函数参数,因为相关的函数参数是 [...] 一组重载函数,并且 [...] 多个函数,因此无法对其进行参数推导匹配函数参数类型

该确定是在不考虑可能已经在别处推导出的模板参数的情况下做出的,因此T必须推导出为的事实int与此处无关。这使得整个参数M (fun)(T)成为非推导上下文。因此M,正如 Clang 所声称的那样,无法推断。

在确定第二个参数是否为非推导上下文时,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); 
}
于 2013-07-30T00:41:47.787 回答
2

我之前的回答(现已删除)是错误的。叮当是错误的。

编译器应该能够推断出类型M,因为函数参数是M(fun)(T). 注意M函数指针参数列表中没有,所以这对应14.8.2.5中的T()(C++11)/ (C++93):T(*)()

where(T)表示一个参数类型列表,其中至少一个参数类型包含 a T,并且()表示一个参数类型列表,其中没有参数类型包含 a T

于 2013-07-23T11:25:32.003 回答