Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'make_shared' is ambiguous

Tags:

c++

boost

The following compiles unless B0RKEN is defined (like with -DB0RKEN on the command line):

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

using boost::shared_ptr;
using boost::make_shared;

using my_fn = std::function<void()>;

void foo()
{
        my_fn fn = [](){};

#ifdef B0RKEN
        shared_ptr<my_fn> k = make_shared<my_fn>(fn);
#else
        shared_ptr<int> k = make_shared<int>(0);
#endif
}

It seems like boost is playing some funny games, which may be why this code fragment has this issue. What I don't understand is why it works with shared_ptr<int> but not shared_ptr<my_fn>.

I am not interested in debating whether I should be using boost or std shared pointers.

I get the following error from clang++:

foo.cpp:15:24: error: call to 'make_shared' is ambiguous
        shared_ptr<my_fn> k = make_shared<my_fn>(fn);
                              ^~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:4670:1: note: candidate function [with _Tp =
      std::__1::function<void ()>, _Args = <std::__1::function<void ()> &>]
make_shared(_Args&& ...__args)
^
/opt/local/include/boost/smart_ptr/make_shared_object.hpp:246:87: note: candidate function [with T = std::__1::function<void ()>, Args =
      <std::__1::function<void ()> &>]
template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
                                                                                      ^
1 error generated.

And from g++:

foo.cpp: In function ‘void foo()’:
foo.cpp:15:45: error: call of overloaded ‘make_shared(my_fn&)’ is ambiguous
  shared_ptr<my_fn> k = make_shared<my_fn>(fn);
                                             ^
foo.cpp:15:45: note: candidates are:
In file included from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/smart_ptr/make_shared.hpp:15:0,
                 from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/make_shared.hpp:15,
                 from foo.cpp:3:
PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/smart_ptr/make_shared_object.hpp:246:87: note: typename boost::detail::sp_if_not_array<T>::type boost::make_shared(Args&& ...) [with T = std::function<void()>; Args = {std::function<void()>&}; typename boost::detail::sp_if_not_array<T>::type = boost::shared_ptr<std::function<void()> >]
 template< class T, class... Args > typename boost::detail::sp_if_not_array< T >::type make_shared( Args && ... args )
                                                                                       ^
In file included from PATH_TO_TOOLCHAIN/gcc-4.9.3/include/c++/4.9.3/memory:82:0,
                 from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/config/no_tr1/memory.hpp:21,
                 from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/smart_ptr/shared_ptr.hpp:23,
                 from PATH_TO_TOOLCHAIN/boost-1.59.0/include/boost/shared_ptr.hpp:17,
                 from foo.cpp:2:
PATH_TO_TOOLCHAIN/gcc-4.9.3/include/c++/4.9.3/bits/shared_ptr.h:600:5: note: std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = std::function<void()>; _Args = {std::function<void()>&}]
     make_shared(_Args&&... __args)
     ^
like image 714
Gary Jackson Avatar asked Dec 30 '15 15:12

Gary Jackson


People also ask

Why is Make_shared more efficient?

One reason is because make_shared allocates the reference count together with the object to be managed in the same block of memory.

What is Make_shared?

make_shared is exception-safe. It uses the same call to allocate the memory for the control block and the resource, which reduces the construction overhead. If you don't use make_shared , then you have to use an explicit new expression to create the object before you pass it to the shared_ptr constructor.


1 Answers

The type of my_fn is std::function<void()>;, residing in namespace std.

When you try to call make_shared<my_fn>(fn); it sees both boost version (because you wrote using boost::make_shared;) and std version by virtue of ADL.

int does not belong to std namespace and std version of make_shared is not considered.

Prefer to use qualified names instead when possible to avoid such problems.

like image 63
Revolver_Ocelot Avatar answered Nov 11 '22 12:11

Revolver_Ocelot