【问题标题】:Syntax differences in variadic template parameter pack forwarding可变参数模板参数包转发的语法差异
【发布时间】:2017-04-25 13:37:11
【问题描述】:

在使用可变参数模板时,我遇到了两种不同的方式来编写对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)...);
}

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

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

【问题讨论】:

  • 第一个是错误的,除了单元素包外实际上并没有编译。
  • 这就是所谓的包扩展。使用one(2, 2.3, 2.3f); 调用第一个示例将使函数体foo(std::forward&lt;int&amp;&amp;, double&amp;&amp;, float&amp;&amp;&gt;(2, 2.3, 2.3f) 无法编译。

标签: c++ c++11 variadic-templates perfect-forwarding


【解决方案1】:

... 位置告诉编译器在哪里展开包,对于它之前的东西中的每个元素一次(很难说容易,但我将在下面说明)。

让我们考虑一个包T = {int, double, char}args = {1, 2.0, '3'}

您的第一个示例 (one) 将在&lt;&gt; 内部扩展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'));

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-30
    • 2016-12-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 2013-01-06
    相关资源
    最近更新 更多