Why is a non-const rvalue move constructor called in this case?

  • A+
Category:Languages

I have seen the related questions and they mostly talk about if we should have const rvalue references as a parameter or not. But I still fail to reason why a non-const move constructor is being called in the following code:

    #include <iostream>     using namespace std;      class A      {     public:       A (int const &&i) { cout << "const rvalue constructor"; }       A (int &&i) { cout << "non const rvalue constructor"; }    };      int const foo (void)    {      const int i = 3;      return i;    }    int main (void)   {      A a(foo());   } 

 


Here is a slightly modified version of your code:

#include <iostream>  #if 0 using T = int; #else struct T {T(int){}}; #endif      using namespace std;     class A {       public:       A (T const &&i) { cout << "const rvalue constructor"; }       A (T &&i) { cout << "non const rvalue constructor"; }    };      T const    foo (void)    {      const T i = 3;      return i;    }    int main()   {     A a(foo());   } 

When T == int, you get the non-const overload. When T is a class type, you get the const overload. This behavior falls out of section 8.2.2 [expr.type]/p2:

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

Translation: The language doesn't have const-qualified scalar prvalues. They simply don't exist.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: