Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么在未赋值的操作数中进行包扩展会导致最后一个元素?_C++_Templates_C++11_Variadic Templates_Comma Operator - Fatal编程技术网

C++ 为什么在未赋值的操作数中进行包扩展会导致最后一个元素?

C++ 为什么在未赋值的操作数中进行包扩展会导致最后一个元素?,c++,templates,c++11,variadic-templates,comma-operator,C++,Templates,C++11,Variadic Templates,Comma Operator,我可以在decltype()中执行此操作: auto g()->decltype(1,”,true,新int); 但不是这个: 模板 自动g(Args&&…Args)->decltype(Args; 它失败是因为包扩展出现在decltype()中,但我认为包扩展会导致参数列表以逗号分隔。因此g(a,b,c)的返回类型将是decltype(c),因为逗号运算符是如何工作的(它返回最后一个元素)。当您在函数参数列表、模板参数列表、初始值设定项列表等内部展开时,它会起作用。但为什么不是这样呢?参数

我可以在
decltype()中执行此操作:

auto g()->decltype(1,”,true,新int);
但不是这个:

模板
自动g(Args&&…Args)->decltype(Args;

它失败是因为包扩展出现在
decltype()
中,但我认为包扩展会导致参数列表以逗号分隔。因此
g(a,b,c)
的返回类型将是
decltype(c)
,因为逗号运算符是如何工作的(它返回最后一个元素)。当您在函数参数列表、模板参数列表、初始值设定项列表等内部展开时,它会起作用。但为什么不是这样呢?

参数包仅在某些情况下展开。您可以通过搜索“包扩展”在标准中找到它们。比如说,

功能参数包是包扩展(14.5.3)

(8.3.5/14)


除非在某个地方明确指定包扩展发生在特定上下文中,否则它不会发生,并且通常被语法禁止(即语法不正确)。例如,
decltype
需要一个表达式作为其操作数
1,“,true,new int
确实是一个表达式(
是逗号运算符),但
args…
不是一个表达式。但是,
args…
是一个表达式列表,因此可以使用它,例如在函数调用中。

逗号运算符与逗号表达式分隔符不同

逗号运算符接受两个表达式,计算左侧,丢弃它,计算右侧,然后返回结果

当您有表达式列表(如函数调用或初始值设定项列表)时,将使用表达式分隔符

decltype(a,b,c)
decltype(
expression
,而不是
decltype(
expression list
)。这意味着
decltype
中的
是运算符逗号

通常,
扩展仅在语法允许表达式列表时才起作用。
“generated”是表达式分隔符,而不是逗号运算符

我不知道有什么方法可以使用
模拟
操作符的行为,包括执行顺序。如果您不关心它们的评估顺序,可以执行以下操作:

template<class T, class... Ts>
struct last_type_helper{using type=T;};
template<class T0, class T1, class... Ts>
struct last_type_helper<T0, T1, Ts...>:last_type_helper<T1, Ts...>{}
template<class... Ts>
using last_type=typename last_type_helper<Ts...>::type;

template<class T0>
T0&& last_expression( T0&& t0 ) { return std::forward<T0>(t0); }
template<class T0, class...Ts>
auto last_expression( T0&& t0, Ts&&...ts )->last_type<T0, Ts...>&& {
  return last_expression( std::forward<Ts>(ts)... );
}
模板
结构last_type_helper{using type=T;};
模板
结构last_type_helper:last_type_helper{}
模板
使用last\u type=typename last\u type\u helper::type;
模板
T0&&last_表达式(T0&&T0){return std::forward(T0);}
模板
自动最后一个表达式(T0&&T0,Ts&&Ts)->最后一个类型&&{
返回最后一个_表达式(std::forward(ts)…);
}
然后

模板
自动g(Args&&…Args)->decltype(最后一个表达式(Args…);
工作也一样

template<class...Args>
auto g(Args&&...args) -> last_type<Args...>;
模板
自动g(Args&&…Args)->最后一种类型;

这是本末倒置,不是吗?

我有理由相信这不是它的工作原理。包扩展永远不会给你一个带有逗号分隔符的表达式。它根据上下文为您提供不同的列表
“根据展开的位置,生成的逗号分隔列表是不同类型的列表:函数参数列表、成员初始值设定项列表、属性列表等。”
。但它永远不会给您一个带有逗号运算符的表达式。它不像宏那样只是文本替换。
template<class...Args>
auto g(Args&&...args) -> last_type<Args...>;