Search code examples
c++rvalue-reference

Why rvalue reference member would be const?


I am trying to write a move constructor for a structure but I can't understand why I fail to call the move constructor of structure member:

#include <memory>

struct C
{
    std::unique_ptr<int[]> mVector;
    size_t                 mSize;

    C() = default;

    C(C &&temp)
    : mVector(temp.mVector)
    , mSize(temp.mSize)
    {}    
};

When I compile this I get:

gcc -c TempTest.cpp
TempTest.cpp: In constructor 'C::C(C&&)':
TempTest.cpp:9:23: error: use of deleted function 'std::unique_ptr<_Tp [], _Dp>::unique_ptr(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = int; _Dp = std::default_delete<int []>]'
9 |     , mSize(temp.mSize)
  |                       ^
In file included from c:/msys64/mingw64/include/c++/10.3.0/memory:83,
             from TempTest.cpp:1:
c:/msys64/mingw64/include/c++/10.3.0/bits/unique_ptr.h:723:7: note: declared here
 723 |       unique_ptr(const unique_ptr&) = delete;
     |       ^~~~~~~~~~

Because in contructor temp is a rvalue reference, it is non-const so temp.mVector should be non-const and should call the unique_ptr move constructor but instead it calls the copy constructor which is deleted. Any idea where is the error?


Solution

  • Why rvalue reference member would be const?

    Don't assume that it's const. You should assume that unique_ptr(const unique_ptr&) is merely the best match, from the available constructors.

    Because in constructor temp is a rvalue reference

    Surprise! It is not an r-value reference.

    The variable temp is bound to an r-value, when the constructor is called. And now that it's a named variable, it's no longer a "temporary". It has become an l-value.

    Since you know that the value was an r-value when the constructor was called, you can safely move the members, converting them back to an r-value.

    C(C &&temp)
    : mVector(std::move(temp.mVector))
    //        ^^^^^^^^^ We know that temp CAME FROM an r-value,
    //                  so it can safely be moved.
    , mSize(temp.mSize)
    {}