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

时间:2012-04-19 10:21:57

标签: c++ c++11 comma variadic

我看着“How to properly use references with variadic templates,”并想知道逗号扩展可以走多远。

以下是答案的变体:

inline void inc() { }

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

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

这适用于我的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”,和/或使用后增量;但都没有效果。)

1 个答案:

答案 0 :(得分:4)

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

使用辅助模板功能,它什么都不做:

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)...);