1

I'm currently studying C++ lvalue and rvalue these days. I got a little confuse in below code.

class Test {
public:
    Test(){}
    explicit Test(int _i): i(_i) {}

    void doSomething()& {
        cout << "L value ref" << endl;
    }

    void doSomething()&& {
        cout << "R value ref" << endl;
    }
private:
    int i;
};
void callDoSomething(Test& t) {
    t.doSomething();
}
void callDoSomething(Test&& t) {
    t.doSomething();
}

int main() {
    auto a = Test();
    callDoSomething(a);
    callDoSomething(Test());
    return 0;
}

In above code, I will get this result:

L value ref
L value ref

I have check above code via debugger and pretty sure that in this code snippet: callDoSomething(Test()); It will go to the rvalue reference one which is callDoSomething(Test&& t). But why did it still call the lvalue member function?

I also tried template and still got same result.

template <typename T>
void callDoSomething(T &&t) {
    t.doSomething();
}

I have already read this post and knows that in template version. The T &&t is actually a universal reference. But after check via debugger. The type of t is still Test&& and we can get Test&& &&t. By reference collapsing's definition, we should still get Test&& t.

Can anyone explain why this happen? Thanks a lot!

JasonLu
  • 11
  • 1
  • @user253751 Thanks for the post!. 'Its type is "rvalue reference to string", but it's an lvalue of that type."'. This make sense. – JasonLu Jan 31 '20 at 13:08

1 Answers1

2

The moment you have a variable with a name, it's an lvalue. This means that doAThing(X&& t) takes an argument that's an rvalue; but in the function it's an lvalue called t.

If you were to do std::move(t).doAThing() you'll end up back with an rvalue call again.

UKMonkey
  • 6,941
  • 3
  • 21
  • 30