我看着“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”,和/或使用后增量;但都没有效果。)
答案 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)...);