Clang vs GCC-可变参数模板参数包,后跟具有默认值的参数在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
The code below works in 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进行编译,
But if fails to compile with 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)
^
lang语至少会警告隐式从浮点数到整数的转换。很好,我们可以通过调用 func< float>
来纠正此问题,这会将float参数放入模板包中。因此,如果我注释掉 func()
,它可以很好地编译。
Clang at least warns of the implicit conversion from a float to an int. Fine, we can correct that by calling func<float>
which puts the float parameter into the template pack. So, if I comment out func()
, it compiles fine.
我在标准说法明确地说,可变参数模板包必须是参数声明子句中的最后一件事,只是它变成了非推论上下文。
I can't find anything in the standard saying explicitly that variadic template pack has to be the last thing in the parameter-declaration-clause, just that it becomes a non-deduced context.
我的困惑来自为什么当 func(1)
完全可以接受时,clang不喜欢 func()
的原因。我可以手动定义 func(int optional = 4){cout<<可选<<恩德尔}
,一切都很好(但在传递 int
时,可以使用模板化函数,而不是模板函数,我正确地获得了专门的 func()
在clang和gcc中都起作用。什么是clang强制执行限制了 func()
的使用?
My confusion comes from why clang doesn't like func()
when func(1)
is perfectly acceptable. I can manually define func(int optional = 4) { cout << optional << endl; }
and everything is fine (but instead of the templated function when passing int
I correctly get the specialized func()
in both clang and gcc. What is clang enforcing that restricts the use of func()
?
推荐答案
这实际上由稍微放错地方的 [temp.arg.explicit] / 3 :
This is actually covered by the slightly misplaced [temp.arg.explicit]/3:
尾随模板参数包(14.5.3)不否则推导出的
将被推导出为空的模板参数序列。
A trailing template parameter pack (14.5.3) not otherwise deduced will be deduced to an empty sequence of template arguments.
模板参数包在尾随并因此推导为除 func< float>(3.3f)
以外的所有调用中的空包,也就是说,它们都有效(并且Clang可以很好地编译它们从3.5开始)。
The template parameter pack is trailing and thus deduced to the empty pack in all calls except for func<float>(3.3f)
, that is, they are all valid (and Clang compiles them fine as of 3.5).
但是,编译器不是一旦我们将模板的声明调整为
However, the compilers are not conforming anymore once we adjust the template's declaration to
template <typename... Args, typename=void>
void func(Args... args, int optional = 0)
现在,前面提到的引用不适用(因为 Args
不尾随)和 [temp.deduct.call] / 1 适用:
Now, the aforementioned quote is not applicable (as Args
is not trailing) and [temp.deduct.call]/1 applies instead:
当使用函数参数时包出现在非推导上下文
(14.8.2.5)中,该参数包的类型从不推导。
When a function parameter pack appears in a non-deduced context (14.8.2.5), the type of that parameter pack is never deduced.
(即,这将导致推论失败。)
(I.e. this should yield a deduction failure.)
这篇关于Clang vs GCC-可变参数模板参数包,后跟具有默认值的参数在GCC 4.8中有效,但在Clang 3.5中不适用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!