5

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

这是答案的变体:

inline void inc() { }

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

由于可变参数被扩展为其元素的逗号分隔列表,这些逗号在语义上是否等同于模板/函数参数分隔符,或者它们是否按词法插入,使其适合任何(后预处理器)使用,包括逗号运算符?

这适用于我的 GCC-4.6:

// Use the same zero-argument "inc"

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

但是当我尝试时:

// Use the same zero-argument "inc"

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

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

(我已经尝试在括号中包含“args”,和/或使用后增量;都没有成功。)

4

1 回答 1

6

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

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

template <typename ...Args>
void pass(Args&&...) { }

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

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

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

    pass((++std::forward<Args>(args), 0)...);
于 2012-04-19T11:06:45.927 回答