apple apple
apple apple

Reputation: 10591

convert std::shared_ptr<Derived> to const shared_ptr<Base>&

If I remember correctly (and according to this question), std::shared_ptr<Derived> cannot be bind to const std::shared_ptr<Base>&. But when I tried the following code, it doesn't give me even any warnings.

#include <memory>
struct A{};
struct B:A{};

void Do(const std::shared_ptr<A>&){}

template<typename T>
struct C{};
void DoC(const C<A>&){}

int main()
{
    std::shared_ptr<B> b = std::make_shared<B>();
    Do(b); //accept ?
    /*following lines generate error
    C<B> c;
    DoC(c); //error
    //*/
}

compiler is mingw g++ 5.3.0 with flag -std=c++14 -Wall -Wextra -pedantic -Werror

Same result with Coliru and many other online compiler.

Is there something I missed?

Upvotes: 2

Views: 1000

Answers (2)

apple apple
apple apple

Reputation: 10591

In addition to what already answered, I'd like to point out what passed to the function is a temporary shared_ptr. The code in question works because it's a constshared_ptr& which can bind a temporary.


#include <memory>
struct A{};
struct B:A{};

void Do(const std::shared_ptr<A>&){}
void DoNo(std::shared_ptr<A>&){}
void DoRvalue(std::shared_ptr<A>&&){}
void DoValue(std::shared_ptr<A>){}

int main()
{
    std::shared_ptr<B> b = std::make_shared<B>();
    Do(b); // a temporary is constructed and passed to Do 
    DoNo(b); // not work, temporary cannot bind to lvalue reference
    DoRvalue(b); // OK, temporary bind to rvalue reference
    DoValue(b); // OK
}

https://godbolt.org/z/sW8cf5ohe

Upvotes: 1

Vittorio Romeo
Vittorio Romeo

Reputation: 93274

std::shared_ptr has a constructor that allows the conversion from B to A:

(from cppreference)

template< class Y > 
shared_ptr( const shared_ptr<Y>& r );

9) Constructs a shared_ptr which shares ownership of the object managed by r. If r manages no object, *this manages no object too. The template overload doesn't participate in overload resolution if Y* is not implicitly convertible to T*.


DoC(c) gives you an error because you haven't defined a constructor that does the conversion - a similar constructor will not be implicitly generated for you.

Upvotes: 4

Related Questions