对f1和f2的扣减是否不正确?
template<class... T, class U>
void f1(T..., U){}
template<class... T>
void f2(T..., int){}
int main()
{
f1(1);
f2(1);
return 0;
}g++接受两者,clang只接受f2,msvc拒绝两者。
相关标准措辞:
[temp.deduct.call]
当函数参数包出现在非推导上下文(temp.deduct.type)中时,该参数包的类型永远不会被推导出来。
[temp.deduct.type]p5
未推导的上下文如下:
所以看来MSVC拒绝两者都是正确的吗?
这是否意味着即使您显式地指定模板args,模板的任何实例化也将是错误的?
f1<int>(1, 2); // ill-formed?
f2<int>(1, 2); // ill-formed?如果是这样,为什么一开始就允许这样的声明?
发布于 2016-04-15 08:48:09
对于这个特定的问题,DR1388有一个DR。显然,GCC和CLANG似乎还没有实施CLANG DR1388。
这是否意味着即使您显式地指定模板args,模板的任何实例化也将是错误的? f1(1,2);//畸形?f2(1,2);//畸形? 如果是这样,为什么一开始就允许这样的声明?
如果显式指定模板参数,则不会发生任何扣减,因此上面显示的代码是合法的。
发布于 2018-01-26 04:33:36
我自己也研究过这个问题,我发现很难得到一个清晰的答案。据我所知,f1(1)应该被拒绝,而f2(1)应该被接受。
尽管如此:
正如您所指出的,没有出现在列表末尾的函数参数包是一个非推导的上下文(temp.deduct.type p5):
未推导的上下文如下:
temp.deduct.call p1 (通过CWG 一三八八修改)澄清了这样一个参数包从来没有被推导出来。
当函数参数包出现在一个非推导的上下文中时,就不会推导出该参数包的类型。
此外,temp.arg.explicit p3指定:
未导出的尾随模板参数包(14.5.3)将被推导为模板参数的空序列。
因此,在f2(1)调用中考虑到这一点: pack是一个尾随模板参数包(尽管它不是尾随函数参数包),因此它推断为空包,并且调用是有效的。
但是,对于f1(1),pack也不是一个尾随的模板参数包,因为它后面跟着U,所以在每个temp.arg.explicit p3中它不是一个空包。因此,由于模板参数包T不能推导出对f1(1)的调用,因此它不应该参与过载解析,并且调用会失败。
请注意,在其他讨论中已经提出了几个类似的问题/例子,但它们都有细微的不同:
f(0)调用在CWG 1388和CWG 1399的示例代码中是有效的,因为所讨论的包是一个尾随模板参数包,因此它属于我前面提到的情况。下面是CWG 1399的代码: template void f(T.,int,T.){} int main() { f(0);// OK f(0,0,0);// OK f(0,0,0);// error }https://stackoverflow.com/questions/36640883
复制相似问题