2015-12-30 12 views
5

Poniższe kompiluje chyba B0RKEN jest zdefiniowane (jak z -DB0RKEN na linii poleceń):„make_shared” jest niejednoznaczny

#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 
} 

Wydaje się, że impuls gra kilka zabawnych gier, które mogą być, dlaczego ten fragment kodu ma ten problem. Nie rozumiem, dlaczego działa z shared_ptr<int>, ale nie shared_ptr<my_fn>.

Nie jestem zainteresowany debatą, czy powinienem używać współczynników wspomagających lub współdzielonych.

pojawia się następujący błąd z brzękiem ++:

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. 

A z 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) 
    ^
+0

Jaki kompilator, jaki komunikat o błędzie, jaką wersję boost? – rhashimoto

+0

Czy masz "using namespace std' lub" using std :: makes_shared'? –

Odpowiedz

12

Rodzaj my_fn jest std::function<void()>;, zamieszkały w przestrzeni nazw std.

Podczas próby wywołania widzi obie wersje doładowania (ponieważ napisano using boost::make_shared;) i wersję standardową na podstawie ADL.

int nie należy do std Przestrzeń nazw i wersja standardowa make_shared nie jest brana pod uwagę.

Zamiast tego należy używać nazw kwalifikowanych, aby uniknąć takich problemów.

+0

Dzięki. Mam jedno przewlekłe pytanie. Następujące prace: "shared_ptr > k = make_shared > (0);". Zastanawiam się, dlaczego ADL nie kopie tutaj, ale robi to dla innych rzeczy w std (jak std :: string). –

+0

@GaryJackson ADL działa dla argumentów funkcji. W twoim przykładzie argumentem jest '0', które jest' int' i nie wyzwala ADL. –

+2

Zabawnie, ADL * tylko * kopie tutaj, gdy znajdzie szablon funkcji o tej nazwie bez ADL, jak wyjaśniono [tutaj] (http://stackoverflow.com/questions/2953684/why-doesnt-adl-find-function - szablony). Możesz to przetestować samodzielnie - usunięcie instrukcji using dla 'boost :: make_shared' uniemożliwi zgodnemu kompilatorowi znalezienie' std :: make_shared'. – jaggedSpire