2015-12-30 15 views
5

I seguenti compila meno B0RKEN è definita (come con -DB0RKEN sulla riga di comando):'make_shared' è ambigua

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

Sembra spinta è giocare alcuni giochi divertenti, che possono essere il motivo per cui questo frammento di codice ha questo problema Quello che non capisco è il motivo per cui funziona con shared_ptr<int> ma non con lo shared_ptr<my_fn>.

Non sono interessato a discutere se utilizzare i puntatori condivisi boost o std.

ottengo il seguente errore da 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. 

E da 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

Che compilatore, quale messaggio di errore, quale versione di potenziamento? – rhashimoto

+0

Hai usato 'namespace std' o' using std :: makes_shared'? –

risposta

12

Il tipo di my_fn è std::function<void()>;, residente nel namespace std.

Quando si tenta di chiamare , visualizza sia la versione di potenziamento (perché è stata scritta using boost::make_shared;) sia la versione di std in virtù di ADL.

int non appartiene allo spazio dei nomi std e la versione standard di make_shared non viene considerata.

Preferire l'uso di nomi qualificati, quando possibile, per evitare tali problemi.

+0

Grazie. Ho una domanda persistente. I seguenti lavori: "shared_ptr > k = make_shared > (0);". Mi chiedo perché ADL non calci qui, ma lo fa per altre cose in std (come std :: string). –

+0

@GaryJackson ADL funziona per argomenti di funzione. Nel tuo esempio, l'argomento è '0' che è' int' e non attiva ADL. –

+2

In modo divertente, ADL * eseguirà * * solo qui quando trova un modello di funzione con quel nome senza ADL, come spiegato [qui] (http://stackoverflow.com/questions/2953684/why-doesnt-adl-find-function -templates). Puoi testarlo da solo - rimuovere le istruzioni using per "boost :: make_shared" impedirà a un compilatore conforme di trovare anche 'std :: make_shared'. – jaggedSpire

Problemi correlati