[英]Clang vs GCC - Variadic template parameter pack followed by parameter with default value works in GCC 4.8 but not Clang 3.5
以下代码适用于gcc-4.8.2
#include <iostream>
using namespace std;
template<typename... Args>
void func(Args... args, int optional = 0)
{
cout << optional << endl;
}
int main()
{
func(1);
func(2.1f); // converts 2.1 to int as 'optional' parameter
func<float>(3.3f); // Fine, prints '0'
func(); // gcc OK, fails to compile with clang-3.5
}
它输出:
$ ./a.out
1
2
0
0
但是如果用clang-3.5编译失败,
test_variadic.cpp:15:2: error: no matching function for call to 'func'
func();
^~~~
test_variadic.cpp:5:6: note: candidate function template not viable: requires at least argument 'args', but no arguments were provided
void func(Args... args, int optional = 0)
^
Clang至少警告从float到int的隐式转换。 好的,我们可以通过调用func<float>
来解决这个问题,它将float参数放入模板包中。 所以,如果我注释掉func()
,它编译得很好。
我无法在标准中找到任何明确说明variadic模板包必须是参数声明子句中的最后一件事,只是它变成了非推导的上下文。
我的困惑来自于当func(1)
完全可以接受时为什么clang不喜欢func()
。 我可以手动定义func(int optional = 4) { cout << optional << endl; }
func(int optional = 4) { cout << optional << endl; }
,一切都很好(但不是通过当模板函数int
我正确地得到专业的func()
两个铛和gcc。什么是铛强制执行这个限制使用的func()
这实际上是由略微错位的[temp.arg.explicit] / 3覆盖的:
未以其他方式推导出的尾随模板参数包(14.5.3)将被推导为空的模板参数序列。
模板参数包是尾随的,因此在除func<float>(3.3f)
之外的所有调用中推导到空包,也就是说,它们都是有效的(并且Clang 从3.5开始编译它们)。
但是,一旦我们将模板的声明调整为,编译器就不再符合
template <typename... Args, typename=void>
void func(Args... args, int optional = 0)
现在,上述引用不适用(因为Args
没有尾随),而[temp.deduct.call] / 1适用:
当函数参数包出现在非推导的上下文(14.8.2.5)中时,永远不会推导出该参数包的类型。
(即这会导致演绎失败。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.