为什么std::forward将我的左值变成右值?

template<class T>
struct IntHolder {
    T i;
};

template<class T>
void addOne(T& t) {
    t.i += 1;
}

template<class... Args>
void addAll(Args... args) {
      // Magic to run addOne on each arg
      int dummy[] = { 0, ((void)addOne(std::forward<Args>(args)), 0)... };
}

int main() {
    IntHolder<int> x{2};
    IntHolder<double> t{3};
    addAll(x, t);
    return 0;
}

这个玩具示例无法编译,因为

prog.cc: In instantiation of 'void addAll(Args ...) [with Args = {IntHolder<int>, IntHolder<double>}]':
prog.cc:60:16:   required from here
prog.cc:54:39: error: invalid initialization of non-const reference of type 'IntHolder<int>&' from an rvalue of type 'IntHolder<int>'
       int dummy[] = { 0, ((void)addOne(std::forward<Args>(args)), 0)... };
                                       ^
prog.cc:48:6: note:   initializing argument 1 of 'void addOne(T&) [with T = IntHolder<int>]'
 void addOne(T& t) {

我认为这里会发生的是 addAll 传入两个左值,然后 addOne 将作为左值在每个左值上调用。但是,似乎在此过程中的某个地方,编译器认为参数正在转换为右值。为什么会这样?

回答

您将参数声明为非引用,即按值传递,然后在传递xand 时t,类型将被推导为IntHolder<int>and IntHolder<double>。然后std::forward<Args>将它们转换为右值。

对于转发参考,它应该是

template<class... Args>
void addAll(Args&&... args) {
    //          ^^
    // Args would be deduced as IntHolder<int>&, IntHolder<double>&
    // then std::forward<Args>(args) yields lvalues 
    int dummy[] = { 0, ((void)addOne(std::forward<Args>(args)), 0)... };
}


以上是为什么std::forward将我的左值变成右值?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>