【问题标题】:Compiler error when passing rvalue reference through variadic templates通过Variadic模板传递RValue引用时编译器错误
【发布时间】:2015-10-26 20:47:09
【问题描述】:

有一个要求,我需要通过可变参数模板将右值从 1 个函数传递到另一个函数。为了避免真正的代码复杂性,下面使用int 的最小示例:

void Third (int&& a)
{}

template<typename... Args>
void Second (Args&&... args) {
  Third(args...);
}

void First (int&& a) {
  Second(std::move(a));  // error: cannot bind ‘int’ lvalue to ‘int&&’
  Third(std::move(a));  // OK
}

int main () {
  First(0);
}

First(0) 被正确调用。如果我直接调用Third(int&amp;&amp;),那么使用std::move() 可以正常工作。但是打电话给Second(Args&amp;&amp;...)results in

error: cannot bind ‘int’ lvalue to ‘int&&’
   Third(args...);        ^
note:   initializing argument 1 of ‘void Third(int&&)’
 void Third (int&& a)

实现Second(Args&amp;&amp;...)编译成功的正确方法是什么?

仅供参考:在实际代码中,Second(Args&amp;&amp;...) 是左值、右值和右值引用的混合。因此,如果我使用:

Third(std::move(args...));

it works。但是当参数混合在一起时,就会出现问题。

【问题讨论】:

    标签: c++ templates c++11 variadic-templates rvalue-reference


    【解决方案1】:

    你必须使用std::forward:

    template<typename... intrgs>
    void Second (intrgs&&... args) {
      Third(std::forward<intrgs>(args)...);
    }
    

    【讨论】:

    • 您能否进一步评估为什么std::move 不是一个好主意?
    【解决方案2】:

    要保持右值性,您必须 moveforward 参数

    template<typename... intrgs>
    void Second (intrgs&&... args) {
      Third(std::forward<intrgs>(args)...);
    }
    

    【讨论】:

    • move 会无条件地将它们转换为右值,这不会“保留”右值性。
    • @Barry,您或 Bo 能否进一步评估一下为什么应该首选 std::forward 而不是 std::move
    • @iammilind - std::move 将始终使参数成为右值,即使它最初不是。 std::forward 将保留传递参数的方式(如 Barry 所说)。如果您总是将右值传递给Second,则没有区别。
    猜你喜欢
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 2014-07-27
    • 1970-01-01
    • 2012-09-23
    • 2013-02-18
    • 1970-01-01
    相关资源
    最近更新 更多