Question

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

Was it helpful?

Solution

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) );

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top