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

查看:105
本文介绍了Clang vs GCC-可变参数模板参数包,后跟具有默认值的参数在GCC 4.8中有效,但在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆