也许我错过了一些明显的东西,但是下面的编译和运行,我不知道为什么。我知道this,但在下面的示例中,参数包的位置和默认参数是相反的。它是否违反了默认参数必须最后出现的规则?参数包不能具有默认值。
#include <iostream>
#include <string>
#include <tuple>
template<typename ... Ts>
struct Test
{
int i;
std::string str;
Test(int _i = 0, Ts&& ... _ts)
:
i(_i),
str(std::get<0>(std::forward_as_tuple(std::forward<Ts>(_ts)...)))
{}
};
int main()
{
Test<std::string> t(1, "huh??");
std::cout << "t.i = " << t.i << ", t.str = " << t.str << "\n";
return 0;
}
这会产生
t.i = 1, t.str = huh??
答案 0 :(得分:20)
From 8.3.6 ([dcl.fct.default])/4:
对于非模板函数,可以在以后添加默认参数 同一范围内的函数声明。声明 不同的范围具有完全不同的默认参数集。 也就是说,内部作用域中的声明不会获取默认参数 来自外部范围的声明,反之亦然。 在给定的功能中 声明,参数后面的每个参数都有一个默认值 参数应具有此前一个或前一个提供的默认参数 声明或应是函数参数包。默认参数 不得在以后的声明中重新定义(甚至不是相同的声明) 值)。 [例如:
void g(int = 0, ...); // OK, ellipsis is not a parameter. So it can follow a parameter with a default argument
答案 1 :(得分:10)
作为rsp的最佳答案的补充,值得注意的是,这种行为具有逻辑意义。非默认的非参数包参数不能遵循默认参数,而不会导致必须指定默认参数 - 在这种情况下它不再是默认参数。
例如,如果允许以下内容:
void example(int x=0, int y);
非默认的第二个参数意味着对函数的调用需要结构example(1, 2);
,因为第一个参数不能默认。空参数包不是这种情况。考虑以下功能:
template <typename... T> void example(int x = 0, T&&... t);
在这种情况下,仍然可以通过调用x
example();
答案 2 :(得分:8)
它的原因很简单。有效的参数包总是有一个默认值:参数包可以是空的,这样就不会与缺少默认值必须是最后一个参数的概念相矛盾。