"make_shared" 是含糊不清的

6
以下内容仅在未定义B0RKEN时编译通过(例如在命令行中使用-DB0RKEN):
#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
}

Boost似乎在玩一些有趣的游戏,这可能是这个代码片段存在问题的原因。我不明白的是为什么它可以使用 shared_ptr<int> ,但不能使用 shared_ptr<my_fn>

我不想讨论我是否应该使用boost或std共享指针。

我从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.

从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)
     ^

什么编译器,什么错误信息,什么Boost版本? - rhashimoto
你是否使用了 using namespace std 或者 using std::makes_shared - Revolver_Ocelot
1个回答

13
< p > my_fn 的类型是在命名空间std中的std::function<void()>;

当你尝试调用 make_shared<my_fn>(fn);时,由于ADL的缘故,它同时看到了boost版本(因为你写了using boost::make_shared;)和std版本。

int不属于std命名空间,因此不考虑使用std版本的make_shared

尽可能使用限定名称以避免这样的问题。


谢谢。我还有一个挥之不去的问题。以下代码可以正常工作:"shared_ptr<std::tuple<int>> k = make_shared<std::tuple<int>>(0);"。 我想知道为什么在这里ADL不起作用,但它对std中的其他事物(如std :: string)却起作用。 - Gary Jackson
@GaryJackson ADL适用于函数参数。在您的示例中,参数为0,它是int类型,不会触发ADL。 - Revolver_Ocelot
2
有趣的是,只有在找不到带有 ADL 的函数模板时,ADL 才会在此处启动,如此处所解释的那样。您可以自行测试-删除 boost::make_shared 的使用语句将防止符合规范的编译器找到 std::make_shared - jaggedSpire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接