可变参数模板参数包转发中的语法差异

时间:2016-12-10 01:15:25

标签: c++ c++11 variadic-templates perfect-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)...);
}

根据我的编译器,这些都是有效的语法,并且在大多数情况下编译器不会抱怨。但是我发现了一些情况,其中一个是正确的,但编译器没有详细说明原因。

另一个更正确吗? 它们有不同的用途吗?

1 个答案:

答案 0 :(得分:6)

ReadyQ(): Promise<any> { let result = new Promise<any>((resolve, reject) => { this.Room.subscribe(snapshot => resolve(snapshot), error => reject(error)); } return result; } ReadyQ().then(result => { // do something }).catch(error => console.error(error)); 展示位置告诉编译器扩展包的位置,对于之前的东西中的每个元素一次(难以轻易说出,但我将在下面说明)。

让我们考虑一个包...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

至于为什么这两个编译都很好,如果你只用一个参数调用,结果是相同的。如果你根本没有打电话那么它就不会被实例化。