C++ – Passing shared_ptr as shared_ptr

cc++11castingshared-ptrsmart-pointers

What is the best method to go about passing a shared_ptr of a derived type to a function that takes a shared_ptr of a base type?

I generally pass shared_ptrs by reference to avoid a needless copy:

int foo(const shared_ptr<bar>& ptr);

but this doesn't work if I try to do something like

int foo(const shared_ptr<Base>& ptr);

...

shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);

I could use

foo(dynamic_pointer_cast<Base, Derived>(bar));

but this seems sub-optimal for two reasons:

  • A dynamic_cast seems a bit excessive for a simple derived-to-base cast.
  • As I understand it, dynamic_pointer_cast creates a copy (albeit a temporary one) of the pointer to pass to the function.

Is there a better solution?

Update for posterity:

It turned out to be an issue of a missing header file. Also, what I was trying to do here is considered an antipattern. Generally,

  • Functions that don't impact an object's lifetime (i.e. the object remains valid for the duration of the function) should take a plain reference or pointer, e.g. int foo(bar& b).

  • Functions that consume an object (i.e. are the final users of a given object) should take a unique_ptr by value, e.g. int foo(unique_ptr<bar> b). Callers should std::move the value into the function.

  • Functions that extend the lifetime of an object should take a shared_ptr by value, e.g. int foo(shared_ptr<bar> b). The usual advice to avoid circular references applies.

See Herb Sutter's Back to Basics talk for details.

Best Answer

This will also happen if you've forgotten to specify public inheritance on the derived class, i.e. if like me you write this:

class Derived : Base
{
};

Instead of:

class Derived : public Base
{
};