Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

function overloading ambiguty between bool and boost::shared_ptr<base> when calling with boost::shared_ptr<derived>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

struct base {};
struct derived : public base {};

void g(bool b) {}

void g(boost::shared_ptr<base> b) {}

int main()
{
    boost::shared_ptr<base> spbase = boost::make_shared<derived>();
    boost::shared_ptr<derived> spderived = boost::make_shared<derived>();

    g(true); // ok
    g(spbase); //ok
    g(boost::static_pointer_cast<base>(spderived)); // ok
    g(spderived); // I am ambiguous between g(bool b) and g(boost::shared_ptr<base> b).
}

Can someone explain to me why the call to g(spderived) causes a ambiguity between g(bool) and g(boost::shared_ptr)?

Compiling with gcc version 4.6.3 gives following error:

$ g++ shared_test.cpp -I/c/thirdparty/boost_1_55_0/ -o shared_test shared_test.cpp: In function 'int main()': shared_test.cpp:27:13: error: call of overloaded 'g(boost::shared_ptr&)' is ambiguous shared_test.cpp:27:13: note: candidates are: shared_test.cpp:7:6: note: void g(bool) shared_test.cpp:9:6: note: void g(boost::shared_ptr)

Note: If I add -std=c++11 it compiles fine, but I use c++98/c++03, so this doesn't really help me. Clang and VC produce a similar error, compiled under c++03.

like image 681
randooom Avatar asked Dec 03 '25 14:12

randooom


1 Answers

In C++03 shared_ptr has implicit bool conversion operator, in C++11 it's explicit. This call is ambigious, since in both cases user-defined conversion will be called, conversion to bool, or conversion to shared_ptr<base>, that is defined like this:

template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )

shared_ptr( shared_ptr<Y> const & r,
typename boost::detail::sp_enable_if_convertible<Y,T>::type =
boost::detail::sp_empty() )

#else

shared_ptr( shared_ptr<Y> const & r )

#endif

it's not copy constructor, it's conversion constructor, so chain will be like this

tmp = shared_ptr<base>(spderived);
b = shared_ptr<base>(tmp);

there is only one way to do what you want: construct temporary of type shared_ptr<base>.

g(boost::shared_ptr<base>(spderived));
like image 138
ForEveR Avatar answered Dec 05 '25 02:12

ForEveR



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!