Reputation: 13398
I have a base class:
class Base {
public:
Base(??? new_p) : p(new_p) {}
std::unique_ptr<MyType> p;
}
And a derived class:
class Derived : public Base {
Derived(??? new_p) : Base(new_p) {}
}
What type do I replace the question marks with if I want to construct Derived
? Other changed are also fine. I want to make sure Derived
can be constructed without copying the MyType
that is pointed to by p
.
Upvotes: 3
Views: 285
Reputation: 106096
Depends what you want to support - either or both of the constructors below make sense, from MyType*
or a std::unique_ptr<MyType>&&
, which requires a movable unique_ptr
be supplied by the caller. Simply using std::unique_ptr<MyType>
works too, because std::unique_ptr
has a constructor from other movable instances... just a matter of taste whether you want to emphasise the necessarily-transient nature of the caller's incoming unique_ptr
in your own code.
class Base
{
public:
Base(MyType* new_p) : p(new_p) { }
Base(std::unique_ptr<MyType>&& new_p) : p(std::move(new_p)) { }
std::unique_ptr<MyType> p;
};
class Derived : public Base
{
public:
Derived(MyType* new_p) : Base(new_p) { }
Derived(std::unique_ptr<MyType>&& new_p) : Base(std::move(new_p)) { }
};
See it running here
Upvotes: 1
Reputation: 756
This worked for me. Edit to note I'm using string as the type only to make it easier to read, you must replace it with your type.
#include <memory>
#include <string>
#include <iostream>
#include <utility>
class Base {
public:
Base(std::unique_ptr<std::string> new_p)
: p(std::move(new_p)) {}
std::unique_ptr<std::string> p;
};
class Derived : public Base {
public:
Derived(std::unique_ptr<std::string> new_p)
: Base(std::move(new_p)) {}
};
int main(){
std::unique_ptr<std::string> text(new std::string("Hello world"));
Derived a(std::move(text));
std::cout << *(a.p);
}
Upvotes: 0
Reputation: 109119
I'd replace ???
with std::unique_ptr<MyType>
and then std::move
it in the mem-initializer.
class Base {
public:
Base(std::unique_ptr<MyType> new_p) : p(std::move(new_p)) {}
std::unique_ptr<MyType> p;
};
class Derived : public Base {
Derived(std::unique_ptr<MyType> new_p) : Base(std::move(new_p)) {}
};
You could also use std::unique_ptr<MyType>&&
instead of std::unique_ptr<MyType>
and avoid the std::move
s but I prefer the by-value approach for the reasons listed in this answer.
I would recommend against taking a MyType *
argument. The problem with that solution is that it doesn't convey to the user your intent of taking ownership of the pointer passed to the constructor.
Upvotes: 1