可变模板参数包转发中的语法差异
Syntax differences in variadic template parameter pack forwarding
在使用可变参数模板时,我遇到了两种不同的方式来编写对 std::forward
的调用,但我想知道这两种语法之间的实际区别是什么?
template<typename... T>
void one(T&&... args)
{
foo(std::forward<T&&...>(args...));
}
template<typename... T>
void two(T&&... args)
{
foo(std::forward<T&&>(args)...);
}
根据我的编译器,这些都是有效的语法,并且在大多数情况下,编译器不会报错。但是我发现了一些情况,其中一个或另一个是正确的,但编译器没有详细说明原因。
一个比另一个更正确吗?
它们有不同的用途吗?
...
位置告诉编译器在哪里扩展包,对它之前的每个元素一次(很难简单地表达,但我将在下面说明)。
让我们考虑一包 T = {int, double, char}
和 args = {1, 2.0, '3'}
您的第一个示例 (one
) 将在 <>
内扩展 T
,然后在 ()
内扩展 args
,因此它变为
foo(std::forward<T&&...>(args...)); // becomes:
foo(std::forward<int&&, double&&, char&&>(1, 2.0, '3'));
这不是 std::forward
的工作方式,因为它只需要一个参数。您的第二个示例 (two
) 表示为包中的每个项目扩展对 std::forward
的整个调用一次,因此它变为
foo(std::forward<T&&>(args)...); // becomes:
foo(std::forward<int&&>(1), std::forward<double&&>(2.0),std::forward<char&&>('3'));
至于为什么这两个编译都很好,如果你只用一个参数调用,结果是相同的。如果您根本没有调用它,那么它就不会被实例化。
在使用可变参数模板时,我遇到了两种不同的方式来编写对 std::forward
的调用,但我想知道这两种语法之间的实际区别是什么?
template<typename... T>
void one(T&&... args)
{
foo(std::forward<T&&...>(args...));
}
template<typename... T>
void two(T&&... args)
{
foo(std::forward<T&&>(args)...);
}
根据我的编译器,这些都是有效的语法,并且在大多数情况下,编译器不会报错。但是我发现了一些情况,其中一个或另一个是正确的,但编译器没有详细说明原因。
一个比另一个更正确吗?
它们有不同的用途吗?
...
位置告诉编译器在哪里扩展包,对它之前的每个元素一次(很难简单地表达,但我将在下面说明)。
让我们考虑一包 T = {int, double, char}
和 args = {1, 2.0, '3'}
您的第一个示例 (one
) 将在 <>
内扩展 T
,然后在 ()
内扩展 args
,因此它变为
foo(std::forward<T&&...>(args...)); // becomes:
foo(std::forward<int&&, double&&, char&&>(1, 2.0, '3'));
这不是 std::forward
的工作方式,因为它只需要一个参数。您的第二个示例 (two
) 表示为包中的每个项目扩展对 std::forward
的整个调用一次,因此它变为
foo(std::forward<T&&>(args)...); // becomes:
foo(std::forward<int&&>(1), std::forward<double&&>(2.0),std::forward<char&&>('3'));
至于为什么这两个编译都很好,如果你只用一个参数调用,结果是相同的。如果您根本没有调用它,那么它就不会被实例化。