Sign in to follow this  
owl

Casting boost::shared_ptr(Derived) to boost::shared_ptr(Base)

Recommended Posts

owl    376
Hello, I have this method which takes a reference to a boost::shared_ptr<Base> as parameter and I'd like to pass a boost::shared_ptr<Derived> to it, but for some reason I can't.
class Base {};

class Derived : public Base {};

void add (boost::shared_ptr<Base>& obj) {}

int main()
{
   boost::shared_ptr<Derived> d (new Derived());
   add (d);
}
Throws:
error: no matching function for call to `add(boost::shared_ptr<Derived>&)'
note: candidates are: void add(boost::shared_ptr<Base>&)
Could you orient me on this? tnx.

Share this post


Link to post
Share on other sites
owl    376
Quote:
Original post by SiCrane
This doesn't work for regular pointers. Why do you expect it to work with smart pointers?


Wait...



class Base
{
public:
virtual void print () {}
};

class Derived : public Base
{
public:
virtual void print () {cout <<"hello!";}
};

void add (Base* obj)
{
obj->print();
}

int main()
{
Derived* d = new Derived();
add (d);

return 0;
}

Share this post


Link to post
Share on other sites
_moagstar_    465
I use boost::shared_dynamic_cast for this kind of thing :


struct Base
{
virtual void print() {}
};

struct Derived : public Base
{
virtual void print() { std::cout << "Derived\n"; }
};

void print(boost::shared_ptr<Base>& obj)
{
obj->print();
}

int main()
{
boost::shared_ptr<Derived> d (new Derived());
print(boost::shared_dynamic_cast<Base>(d));
}



Are there any situations where this would go wrong?

Share this post


Link to post
Share on other sites
Cygon    1219
Why so complicated? You don't need dynamic_cast for an upcast.

class Base {};
class Derived : public Base {};

void Bar(const shared_ptr<Base> &base) {}

void Foo() {
Bar(shared_ptr<Derived>(new Derived()));
}


All that's wrong with your original example is that it's not const-correct.

If you pass a shared_ptr<Base> & (a reference to shared_ptr) to your method, that means the method can put any other object deriving from Base into the shared pointer.

This of course is incompatible with the original pointer, which only takes objects of type Derived, so if your method put an instance of OtherDerived in it, after the method returns, you would end up with a shared_ptr<Derived> that carries an OtherDerived instance.

-

Now if the non-const shared_ptr reference was intentional, you need to cast. But a temporary shared_ptr (without the dynamic cast) should solve that problem, too:

class Base {};
class Derived : public Base {};

void Bar(shared_ptr<Base> &base) {}

void Foo() {
shared_ptr<Derived> derived(new Derived());
shared_ptr<Base> base = derived;
Bar(base);
}

Share this post


Link to post
Share on other sites
_moagstar_    465
You're right, shared_dynamic_cast is not appropriate in this situation - I don't think I've properly woken up yet. But there are a bunch of casts in shared_ptr.hpp, which pretty much create the temporary for you, and maybe a bit more explicit as to the intention.

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by Cygon
Now if the non-const shared_ptr reference was intentional, you need to cast.

No, a cast won't work in standard C++. The result of a cast is an rvalue, and an rvalue can't be bound to a non-const reference.

Share this post


Link to post
Share on other sites
owl    376
Quote:
Original post by Cygon
Why so complicated? You don't need dynamic_cast for an upcast.

*** Source Snippet Removed ***

All that's wrong with your original example is that it's not const-correct.

If you pass a shared_ptr<Base> & (a reference to shared_ptr) to your method, that means the method can put any other object deriving from Base into the shared pointer.

This of course is incompatible with the original pointer, which only takes objects of type Derived, so if your method put an instance of OtherDerived in it, after the method returns, you would end up with a shared_ptr<Derived> that carries an OtherDerived instance.

-

Now if the non-const shared_ptr reference was intentional, you need to cast. But a temporary shared_ptr (without the dynamic cast) should solve that problem, too:

*** Source Snippet Removed ***


Cool. The situation I have is that I need to keep a pointer to Derived before passing it to the method that takes a Base. I was trying to avoid having to write the declaration of a Base pointer and asigning the derived to it to be able to pass it to the method.

I guess I'll just pass the shared_ptr by value to the method that is going to do exactly that whitout me being required to code it by myself.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this