...(省略号)应该放在 C++ 参数包扩展中的哪里? std::forward 在括号内部还是外部? [重复]

问题描述 投票:0回答:2

我是C++参数包扩展的新手,长期以来一直对

...
(省略号)的位置感到困惑,例如:

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

为什么没有

std::forward<Args>(args...)
?我应该遵守什么规则?

c++ c++11 c++17 pack-expansion
2个回答
8
投票

查看 https://en.cppreference.com/w/cpp/language/parameter_pack,特别是“包扩展”部分。

基本上,包扩展中的“...”几乎就像一个宏:在某种程度上,它创建了更多源代码。 “...”之前的内容都会为每个参数重复(并且包名称替换为所述参数),因此像

func(args...)
这样的内容将被扩展为“func(a, b, c)”,而
 func(args)...
会变成“func(a), func(b), func(c)”。

std::forward
仅接受一个参数并生成一个转发项:
func(std::forward(args)...)
将变成单个转发的列表:
func(std::forward(a), std::forward(b), std::forward(c))
。因此,它需要一个参数列表,并生成一个转发参数列表


6
投票

从语法上来说,

std::forward<Args>(args)...;
没有意义。 您只能在括号或大括号内使用包扩展。

如果你要调用一个函数,比如

foo
,那么你会写:

foo(std::forward<Args>(args)...)

这将是一个后缀表达式

foo(/* ... */)
,其中包含一个表达式列表,它是一个初始化器列表,带有单个初始化器子句
std::forward<Args>(args)
和一个
...

换句话说,

...
不是表达式的一部分;它是表达式列表的一部分。 因此,
...
是“最外层”的东西,因为它的优先级低于任何表达式。
*args...
args()...
将分别将
*
()
应用于
args
中的每个参数。 您可以将
X...
视为一条指令:

对包中的每个元素执行

X

std::forward<Args>(args...)
是错误的,因为这里的
...
适用于调用std::forward时参数的
initializer-list
,但
std::forward
不是可变参数函数模板。 它不会转发每个参数,而是尝试调用
std::forward
并传递整个包。

另请参阅如何对可变参数函数中的所有参数调用 std::forward?

© www.soinside.com 2019 - 2024. All rights reserved.