J Dumont
J Dumont

Reputation: 113

How to return reference of unique_ptr<Derived> from unique_ptr<Base>?

I work with unique_ptr on derived structs, and I return references to maintain ownership and keep minimal overhead.

Basically, I want a get function to turn unique_ptr<Base> into unique_ptr<Derived>&.

Do you guys see any alternative? The shared_ptr version works OK btw, is it the only path?

Thanks in advance for your input. JD

#include <memory>

struct Base {

};
struct Derived : public Base {
    float position;
    Derived(float position_) : position(position_) {}
};

//SOURCE OF TRUTH
std::unique_ptr<Base> obj; 


//retreive from obj
template<typename T>
std::unique_ptr<T>& get() {
    std::unique_ptr<Base> &p = obj;
    return std::dynamic_pointer_cast<T>(p); //<-- pb: fails because it copies...
}


int main() {
    //storing
    obj = std::make_unique<Derived>(10.0f);

    // ...

    //retrieving
    std::unique_ptr<Derived>& p = get<Derived>();   
    return 0;
}

Upvotes: 0

Views: 603

Answers (3)

user1624886
user1624886

Reputation: 11

Short answer: Don't! Long Answer: A unique pointer deals with ownership and a reference has no ownership semantic. You may return a (const) reference instead. If you need to share ownership use std::shared_pointer.

Upvotes: 0

darune
darune

Reputation: 11146

You can still just do a regular dynamic_cast with the raw pointer, ie.:

template<typename T>
T* get() {
    std::unique_ptr<Base> &p = obj;
    return dynamic_cast<T*>(p.get());
}

Semanticly that is ok as raw pointer is taken to mean non-owning.

Upvotes: 1

Caleth
Caleth

Reputation: 63362

get should return a non-owning pointer, because it shouldn't be changing the ownership.

template<typename T>
T * get() {
    return std::dynamic_cast<T *>(obj.get());
}

Upvotes: 1

Related Questions