我可以在decltype()
:中执行此操作
auto g() -> decltype(1, "", true, new int);
但不是这个:
template <class... Args>
auto 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(
表达式)
,而不是decltype(
表达式列表)
。这意味着decltype
中的,
是运算符逗号。
通常,...
扩展只有在语法允许表达式列表时才有效。"生成"的,
是表达式分隔符,而不是逗号运算符。
我不知道有什么方法可以使用...
来模拟,
运算符的行为,包括执行顺序。如果你不在乎他们的评估顺序,你可以这样做:
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)... );
}
然后
template<class...Args>
auto g(Args&&...args) -> decltype(last_expression(args...));
有效,也是
template<class...Args>
auto g(Args&&...args) -> last_type<Args...>;
本末倒置,不是吗?