繁体   English   中英

Clang vs GCC - Variadic模板参数包后跟带默认值的参数适用于GCC 4.8但不适用于Clang 3.5

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM