Search code examples
c++c++11unique-ptrvisual-c++-2012

Copying std::unique_ptr's value via dereferencing


I wrote the following code where I try to copy the value of unique_ptr object into a structure.

#include <iostream>
#include <memory>
using namespace std;

struct S {
    S(int X = 0, int Y = 0):x(X), y(Y){}

    // S(const S&) {}
    // S& operator=(const S&) { return *this; }

    int x;
    int y;
    std::unique_ptr<S> ptr;
};

int main() {
    S s;
    s.ptr = std::unique_ptr<S>(new S(1, 4));
    S p = *s.ptr; // Copy the pointer's value
    return 0;
}

It pops up errors in Visual C++ 2012:

IntelliSense: no suitable user-defined conversion from "S" to "S" exists
IntelliSense: no operator "=" matches these operands operand types are: std::unique_ptr> = std::unique_ptr>
error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'

Unless I uncomment the lines where I attempted to define a copy constructor and =operator. This gets rid of the compiler errors but not the IntelliSense errors. It compiles regardless of IntelliSense errors showing in error list.

So, why cannot it just use the default functions and compile with them? Am I doing the copy of value the right way? How should I define the copy constructor if it needs one?


Solution

  • The copy constructor is not implicitly generated because you have a user-defined constructor, which is why your attempt to copy an S fails.

    But still, unique_ptr are not copyable, only movable, so you can use a move constructor for S :

    S(S&& other) : x(other.x), y(other.y), ptr(std::move(other.ptr))
    {
          
    }
    

    And call it :

    S p = std::move(s); // Move s to p
    

    Live demo