我可以在decltype()
:
auto g() -> decltype(1, "", true, new int);
但不是这样:
template <class... Args>
auto g(Args&&... args) -> decltype(args...);
它失败了,因为包{2}中出现了包扩展,但我认为包扩展会导致以逗号分隔的参数列表。因此,decltype()
的返回类型将是g(a, b, c)
,因为逗号运算符的工作方式(它返回最后一个元素)。当您在函数参数列表,模板参数列表,初始化列表等内部展开时,它可以工作。但为什么这不是这种情况?
答案 0 :(得分:5)
参数包仅在某些情况下展开。您可以通过搜索&#34; pack expansion&#34;在标准中找到它们。例如,
功能参数包是包扩展(14.5.3)。
(8.3.5 / 14)。
除非在特定上下文中明确指定包扩展,否则它不会发生,并且通常被语法禁止(即,语法上不正确)。例如,decltype
需要表达式作为其操作数。 1, "", true, new int
确实是一个表达式(,
是逗号运算符)但args...
不是表达式。但是,args...
是表达式列表,因此可以在函数调用中使用例如。
答案 1 :(得分:4)
逗号运算符与逗号表达式分隔符不同。
逗号运算符采用两个表达式,计算左侧,丢弃它,计算右侧,并返回结果。
当您有表达式列表(如函数调用或初始化列表)时,将使用表达式分隔符。
decltype(a,b,c)
是decltype(
表达式)
,而不是decltype(
表达式列表)
。这意味着,
中的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)... );
}
然后
template<class...Args>
auto g(Args&&...args) -> decltype(last_expression(args...));
和
一样有用template<class...Args>
auto g(Args&&...args) -> last_type<Args...>;
将车推到马后面,没有?