可变参数扩展可以用作逗号运算符调用链吗?

CTM*_*ser 5 c++ variadic comma c++11

我在看“如何正确使用可变参数模板的引用”,并想知道逗号扩展可以走多远。

这是答案的一个变体:

inline void inc() { }

template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t; inc(args...); }
Run Code Online (Sandbox Code Playgroud)

由于可变参数被扩展到一逗号-分隔它们的元素的列表,是那些逗号语义上等同于模板/功能参数的分离器,或者他们插入词法,使得它们适用于任何(-预处理后)的使用,包括逗号操作符?

这适用于我的 GCC-4.6:

// Use the same zero-argument "inc"

template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t, inc(args...); }
Run Code Online (Sandbox Code Playgroud)

但是当我尝试时:

// Use the same zero-argument "inc"

template<typename T,typename ...Args>
inline void inc(T& t, Args& ...args) { ++t, ++args...; }
Run Code Online (Sandbox Code Playgroud)

我不断收到解析错误,期待“;” 在“...”之前,并且“args”不会扩展其包。为什么不起作用?是因为如果“args”为空,我们会得到一个无效的标点符号?合法吗,我的编译器不够好?

(我试过在括号中围绕“args”,和/或使用后增量;都没有奏效。)

nos*_*sid 6

仅在某些上下文中才允许解包,逗号分隔的语句不属于它们。用你的话:扩展是语义上的,而不是词汇上的。但是,这并不重要,因为还有其他几种方法可以做到。已经有一些模式/习惯用法可以编写简单的可变参数函数。一种方法:

使用辅助模板函数,它什么都不做:

template <typename ...Args>
void pass(Args&&...) { }
Run Code Online (Sandbox Code Playgroud)

不使用逗号运算符,而是将表达式传递给此函数:

template <typename ...Args>
void inc(Args&&... args)
{
    pass(++std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)

如果表达式必须更复杂,您可以在扩展中使用逗号运算符。如果某些operator++有返回类型,这可能对您有用void

    pass((++std::forward<Args>(args), 0)...);
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是错误的(即使用危险)。参数求值的顺序未定义,因此副作用的顺序也未定义。它应该是一个`template&lt;class T&gt; void pass(T)`函数,以`initializer_list`作为参数:`pass({(something)...})`。http://stackoverflow.com/questions/621542/compilers-and-argument-order-of-evaluation-in-c (3认同)