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

Started by
9 comments, last by owl 14 years, 10 months ago
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.
[size="2"]I like the Walrus best.
Advertisement
This doesn't work for regular pointers. Why do you expect it to work with smart pointers?
Then they say c++ alows you to shoot yourself in the foot...
[size="2"]I like the Walrus best.
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;}
[size="2"]I like the Walrus best.
Base * != Base *&
:O
[size="2"]I like the Walrus best.
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?
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);}

Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
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.
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.

This topic is closed to new replies.

Advertisement