5

我知道我们不能像使用逗号运算符链一样使用可变参数扩展。在那个问题中,样本是这样的:

template<typename... Args>
inline void increment_all(Args&... args) 
{
    ++args...; 
}

首先递增或扩展可能是模棱两可的,因此括号不会受到伤害:

template<typename... Args>
inline void increment_all(Args&... args)
{
    (++args)...; 
}

或类似的东西:

template<typename... Args>
void cout_all(Args&&... args)
{
    (std::cout << std::forward<Args>(args))...; 
}

我知道我们可以使用一些递归技巧来获得我们想要的东西,就像这样。我不知道为什么标准不描述这种行为?我的意思是,背后的原因是什么?

4

1 回答 1

5

允许包扩展的其他上下文是列表,其中逗号是列表元素之间的分隔符,而不是运算符。

例如,f(args...)展开为函数参数列表,tuple<Args...>展开为模板参数列表。

在您的示例中,包扩展形成一个语句,语句的子表达式之间的逗号是逗号运算符,它可能被重载,导致任意复杂的代码,并且与内置逗号运算符不同,它不强制从左到右评估. 如果您的(std::cout << std::forward<Args>(args))...; 示例以未指定的顺序写出 args,您会感到惊讶,因为参数包中的一种类型重载operator<<并且operator,破坏了评估顺序。

这样做不会是对当前规则的简单扩展,这将是一个完全不同的背景,具有非常不同的效果。

首先递增或扩展可能是模棱两可的,因此括号不会受到伤害:

No, it wouldn't be ambiguous. It's OK to use f(++args...) and it's clear and unambiguous. The difficulty with your suggestion is not how to parse ++args... it's what happens after you expand it to a statement containing comma operators.

于 2013-01-20T23:29:20.437 回答