参数包函数参数可以默认吗?

Posted

技术标签:

【中文标题】参数包函数参数可以默认吗?【英文标题】:Can parameter pack function arguments be defaulted? 【发布时间】:2015-05-19 20:47:46 【问题描述】:

这是 gcc 4.9.2 和 clang 3.5.2 的重点 分歧。程序:

template<typename ...Ts>
int foo(int i = 0, Ts &&... args)

    return i + sizeof...(Ts);


int main()

    return foo();

编译时没有来自 gcc (-std=c++11 -Wall -pedantic) 的注释。 Clang 说:

error: missing default argument on parameter 'args'

foo 修改为:

template<typename ...Ts>
int foo(int i = 0, Ts &&... args = 0)

    return i + sizeof...(Ts);

clang 没有抱怨,但 gcc 说:

error: parameter pack ‘args’ cannot have a default argument

哪个编译器是正确的?

【问题讨论】:

你可以通过重载来解决它:template &lt;typename... Ts&gt; int foo(int i, Ts&amp;&amp;...) return i + sizeof...(Ts); inline int foo() return foo(0); 【参考方案1】:

从 8.3.6 ([dcl.fct.default])/3:

不应为参数包指定默认参数。

从 8.3.6 ([dcl.fct.default])/4:

在给定的函数声明中,带有默认实参的形参后面的每个形参都应在此声明或先前声明中提供默认实参,或者应为函数形参包。

所以这允许像void f(int a = 10, Args ... args) 这样的代码,或者确实像你的第一个sn-p。 (感谢@T.C. 查找第二句话!)

【讨论】:

[dcl.fct.default]/4 ("在给定的函数声明中,带有默认参数的参数后面的每个参数都应在此声明或先前声明中提供默认参数,或者应为一个函数参数包。”)似乎允许第一个版本。 @KerrekSB 是的,所以它允许 GCC 接受的版本。 @T.C.:是的,谢谢,如果您不介意的话,我已将其吸收到帖子中 :-) clang 错误提交:2302823029 已在主干中修复,因此将在下一版本的 clang 中修复。真快!【参考方案2】:

Kerrek SB 说,这是不可能的。相反,您可以做的是使用std::tuple

template <class ... Args>
void foo( std::tuple<Args...> t = std::tuple<int>(0) )

【讨论】:

以上是关于参数包函数参数可以默认吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python:函数的参数、混搭、开包

我可以从以前的参数中设置默认参数吗?

函数模板参数包后跟模板参数和特化

可以在具有默认值(作为可选参数)的参数中分配 const 变量吗?

c# 请问数组能作为参数传递吗? 如果可以如何传递呢?

为 JavaScript 函数设置默认参数值