2
#include <iostream>
#include <memory>

class Base{
};
class Derive : public Base{
};

void foo(std::shared_ptr<Base>& p){
}
void bar(const std::shared_ptr<Base>& p){
}

int main(){

    auto base = std::make_shared<Base>();
    foo(base);
    bar(base);

    auto derive = std::make_shared<Derive>();
    foo(derive);
    bar(derive);

    return 0;
}

g++ -std=c++0x test.cpp

The compiler says:

test.cpp:21:5: error: no matching function for call to 'foo'
    foo(derive);
    ^~~
test.cpp:9:6: note: candidate function not viable: no known conversion from 'std::__1::shared_ptr<Derive>' to
      'std::shared_ptr<Base> &' for 1st argument
void foo(std::shared_ptr<Base>& p){

Could you explain why you can't pass the shared_ptr of derived class to foo(), while you can pass it to bar() that receives const reference of the shared_ptr.

Sorry for my poor English. Thanks.

Gambit1614
  • 8,547
  • 1
  • 25
  • 51
yamasv
  • 39
  • 3
  • This is lifetime extension of a temporary. I'm certain this is a duplicate of an existing question – Justin Sep 15 '17 at 23:44
  • May help you to get it fast: https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ – Steephen Sep 16 '17 at 00:01
  • https://stackoverflow.com/questions/24943093/does-const-bind-to-all-prvalues-and-xvalues – Steephen Sep 16 '17 at 00:13
  • Usually you should not pass a `std::shared_ptr` by non `const` reference... as it does not make much much sense to modify the pointer from inside the function if you pass a smart pointer to a derived class. – Phil1970 Sep 16 '17 at 04:06

1 Answers1

2

Calling foo(derive) requires a temporary std::shared_ptr<Base> to be constructed from derive, and a non-const lvalue-reference cannot bind to a temporary object. To call foo, you will need to construct a named std::shared_ptr<Base> that you can pass into it:

auto derive = std::make_shared<Derive>();
std::shared_ptr<Base> b = derive;
foo(b);

bar(derive) is fine, since a const reference can bind to a temporary. An unnamed temporary std::shared_ptr<Base> is constructed from derive and a reference to that temporary is passed to bar.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52