1

I was experimenting with how std::move and std::forward differs, and I have found that I am not able to use std::forward on class field:

name = std::forward<T>(rhs.name);

below is full example. The error I am getting under gcc 6.3 is:

C:/PROGRA~1/MINGW-~1/X86_64~3.0-P/mingw64/lib/gcc/x86_64-w64-mingw32/6.3.0/include/c++/bits/move.h:89:7: error: static assertion failed: template argument substituting _Tp is an lvalue reference type
       static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument"
       ^~~~~~~~~~~~~

I understand that the cause is probably because T is of type WrongUseOfMove. But I wonder if forwarding only a sub variable is possible. For example I could use passed in rhs parameter and forward its fields to different class variables.

#include <iostream>
#include <string>
#include <vector>

class WrongUseOfMove {
 public:
  template<typename T>
  WrongUseOfMove(T&& rhs)
  {
    //name = std::move(rhs.name); // Very wrong!!
    //name = std::forward<T>(rhs.name); // Does not compile, T is WrongUseOfMove instead decltype(rhs.name);
    name = std::forward<decltype(rhs.name)>(rhs.name); // compiles - but is it correct? 
    std::cout << __PRETTY_FUNCTION__ << "\n";
  }

  WrongUseOfMove(){}

  std::string name;
};

int main()
{
  WrongUseOfMove wm;
  WrongUseOfMove wm2 = wm;
}

http://coliru.stacked-crooked.com/a/88d8591ee1478a3f

mike
  • 1,670
  • 11
  • 21
  • While you're experimenting, maybe peruse this question: [What's the difference between `std::move` and `std::forward`?](http://stackoverflow.com/questions/9671749/whats-the-difference-between-stdmove-and-stdforward). – WhozCraig Feb 27 '17 at 08:39

1 Answers1

3

You may use the intuitive way:

name = std::forward<T>(rhs).name;

Demo

Your try:

name = std::forward<decltype(rhs.name)>(rhs.name);

does an unconditional move:

Demo

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • but it will always use copy - right? I would like this line to `move` name if `WrongUseOfMove(T&& rhs)` was called with rvalue, and copy if it was called with lvalue. – mike Feb 27 '17 at 09:22
  • As you can see in the Demo, the `string` is moved as expected with `WrongUseOfMove<1> wm2 = std::move(wm);`. – Jarod42 Feb 27 '17 at 10:07
  • now I see, but I dont fully understand. The move here is done because in `name = std::forward(rhs).name;` name is used on xvalue - right? – mike Feb 27 '17 at 10:47