0

Considering this code

class T {
public:
    T(T& x) = delete;
    T(T&& x) {}
};

void foo(T&& b) {
    T y(b);
}

I was expecting that b; which is an rvalue by declaration; and seemingly usage, should be passed into the move constructor of T in foo().

Instead; I get a compilation error reporting that T& has been deleted.

Replacing it with

void foo(T&& c) {
    T y(std::move(c));
}

Results in the expected success; but obviously one doesn't want to litter their code with std::move everywhere. As tempting as it is to blame visual studio - in this case I suspect it's my understanding that's wrong. Can someone please explain why move constructor isn't used?

UKMonkey
  • 6,941
  • 3
  • 21
  • 30
  • 2
    Remember, anything with a name is an lvalue, no matter what the source of it is. – NathanOliver Oct 07 '19 at 20:29
  • table flipping goodness – UKMonkey Oct 07 '19 at 20:33
  • It makes sense if you think about it, since named thing can be on the left hand side of an assignment operator. I for one had to hammer this rule into my head as well as the rvalueness of the reference kept trying to distract me. – NathanOliver Oct 07 '19 at 20:34
  • 1
    "_Names of `rvalue reference` variables are `lvalues` and have to be converted to `xvalues` to be bound to the function overloads that accept `rvalue reference` parameters, which is why move constructors and move assignment operators typically use `std::move`_" [cppreference](https://en.cppreference.com/w/cpp/utility/move) – Ted Lyngmo Oct 07 '19 at 20:34
  • @NathanOliver template parameters and enumeration constants are exceptions to that rule – Brian Bi Oct 07 '19 at 20:37

0 Answers0