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

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

有人知道哪个是正确的以及为什么吗?

谢谢。


你尝试使用test(...,&A)了吗? - Stefano Falasca
Stefano:我尝试了,但没有任何改变。 - Max
而且不应该这样做。没有必要在函数名上使用地址运算符来获取函数指针。(同样地,没有必要使用 * 显式地解引用函数指针来调用它。)虽然如果你真的想的话可以这样做,但是这并没有什么区别。 - BoBTFish
明白了,我从来没有真正记住过函数指针的语法。谢谢@BoBTFish - Stefano Falasca
1
对于可能因查找错误信息而来到这里的人,可以通过指定类型来解决,即: test<int,int>( 1, A ) - Max
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); 
}

这看起来是正确的。(有一件事让我有点困惑:作为一个无法推导的上下文的“函数参数”是 M (fun)(T),而不是 A 的参数。尽管答案解释了这一点。) - aschepler
这就是为什么我更喜欢在可能的情况下使用函数对象而不是函数指针的原因。 - SirGuy

2

我的先前回答(现已删除)是错误的。Clang是错误的。

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

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


1
+1 是因为我相信你是正确的,这是一个clang的bug。 - Jesse Good
应该不是type (T)才符合标准吗? - maverik
请查看14.8.2.5(11):X<int>(*)(char [6])的形式为template-name<T>(*)(type[i]),这是type(*)(T)的变体。我们能否考虑以下关于函数A的内容:int A(double)的形式为T(*)(type),这是type(*)(T)的变体,因为T是从函数test的第一个参数中推导出来的? - maverik
@Max:我使用从这里下载的N3290。 - maverik
看看Richard Smith的回答。 - bames53
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接