Reputation: 3321
I have the following C++11 construct:
#include <vector>
#include <memory>
class X {
public:
void f(void) { }
};
class Y : public X {
public:
void g(void) { }
};
class A {
private:
std::vector <std::unique_ptr <X> > xs;
public:
void addX(std::unique_ptr <X> &ref) {
xs.push_back(std::move(ref));
}
};
int main() {
A a;
std::unique_ptr <Y> y(new Y());
y->f();
y->g();
std::unique_ptr <X> x(y.release());
a.addX(x);
return 0;
}
In the main function I am trying to build an object of type Y and then add it to the vector of X objects of a. However, I can not directly say a.addX(y)
as std::unique_ptr <Y>
cannot be cast to std::unique_ptr <X>&
. This is why I came up with the workaround where I initialize another unique pointer, x, with the released internal pointer of y.
Although this works, it doesn't seem like the best solution. Is there a better way of passing an object of type std::unique_ptr<Y>
as an argument of type std::unique_ptr<X>&
?
Thanks, - Stan
Upvotes: 3
Views: 2809
Reputation:
You may use a rvalue reference and delegate it with std::move:
#include <vector>
#include <memory>
class X {
public:
void f(void) { }
};
class Y : public X {
public:
void g(void) { }
};
class A {
private:
std::vector <std::unique_ptr<X> > xs;
public:
void addX(std::unique_ptr <X>&& ref) {
xs.push_back(std::move(ref));
}
};
int main() {
std::unique_ptr <Y> y(new Y());
y->f();
y->g();
A a;
a.addX(std::move(y));
// error: no matching function for call to ‘A::addX(std::unique_ptr<Y>&)’
// a.addX(y);
return 0;
}
Your function void addX(std::unique_ptr <X> &ref)
stealing the content internally might be a questionable design.
Upvotes: 2
Reputation: 8824
std::unique_ptr provide already the right overload but you need std::move to use them as unique_ptr is not copyable :
std::unique_ptr<X> x;
std::unique_ptr<Y> y { new Y };
x = std::move(y);
For the very specific question, there is no cast possible, if you need to received unique_ptr of sub classes by reference, then use a template function.
template < typename T, typename = typename std::enable_if< std::is_base_of<X,T>::value>::type >
void foo( std::unique_ptr<T> & ) {
}
And last, as the idea is to get ownership of the pointer, if you pass the unique_ptr by rvalue reference, this works as you wants.
void bar( std::unique_ptr<X> && ) {
}
// then
bar( std::move(y) );
Upvotes: 5