2012-07-23 7 views
5

Ho i seguenti due segmenti di codice. Il primo blocco compila e funziona come previsto. Tuttavia il secondo blocco non viene compilato.Creazione di boost :: thread con un'istanza di std :: shared_ptr object

La mia domanda è, dato il codice qui sotto qual è la sintassi corretta quando si cerca di creare un thread in base a un'istanza di un oggetto che viene approssimata da una shared_ptr?

#include <iostream> 
#include <new> 
#include <memory> 

#include <boost/thread.hpp> 

struct foo 
{ 
    void boo() {} 
}; 

int main() 
{ 
    //This works 
    { 
     foo* fptr = new foo; 
     boost::thread t(&foo::boo,fptr); 
     t.join(); 
     delete fptr; 
    } 

    //This doesn't work 
    { 
     std::shared_ptr<foo> fptr(new foo); 
     boost::thread t(&foo::boo,fptr); 
     t.join(); 
    } 

    return 0; 
} 

L'errore del compilatore:

Error 5 error C2784: 'T *boost::get_pointer(T *)' : could not deduce template argument for 'T *' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 3 error C2784: 'T *boost::get_pointer(const std::auto_ptr<_Ty> &)' : could not deduce template argument for 'const std::auto_ptr<_Ty> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 4 error C2784: 'T *boost::get_pointer(const std::auto_ptr<_Ty> &)' : could not deduce template argument for 'const std::auto_ptr<_Ty> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 8 error C2784: 'T *boost::get_pointer(const boost::shared_ptr<X> &)' : could not deduce template argument for 'const boost::shared_ptr<X> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 9 error C2784: 'T *boost::get_pointer(const boost::shared_ptr<X> &)' : could not deduce template argument for 'const boost::shared_ptr<X> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 1 error C2784: 'T *boost::get_pointer(const boost::scoped_ptr<T> &)' : could not deduce template argument for 'const boost::scoped_ptr<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 2 error C2784: 'T *boost::get_pointer(const boost::scoped_ptr<T> &)' : could not deduce template argument for 'const boost::scoped_ptr<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 6 error C2784: 'T *boost::get_pointer(const boost::reference_wrapper<T> &)' : could not deduce template argument for 'const boost::reference_wrapper<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 7 error C2784: 'T *boost::get_pointer(const boost::reference_wrapper<T> &)' : could not deduce template argument for 'const boost::reference_wrapper<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 10 error C2784: 'T *boost::get_pointer(const boost::intrusive_ptr<T> &)' : could not deduce template argument for 'const boost::intrusive_ptr<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 
Error 11 error C2784: 'T *boost::get_pointer(const boost::intrusive_ptr<T> &)' : could not deduce template argument for 'const boost::intrusive_ptr<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files (x86)\boost\boost_1_47\boost\bind\mem_fn_template.hpp 40 1 htest 

risposta

9

Il problema è che si basa su boost::threadboost::mem_fn per gestire le funzioni membro, e boost::mem_fn (o almeno la versione utilizzata) non sa come utilizzare a std::shared_ptr per richiamare una funzione membro in quanto prevede l'utilizzo di boost::shared_ptr o di una miriade di altri tipi di puntatori intelligenti nell'elenco di errori.

Il puntatore raw funziona perché boost::mem_fn ha già tale sovraccarico. Le soluzioni prevedono l'utilizzo di boost::shared_ptr o std::mem_fn. Quest'ultimo funziona perché std::mem_fn sa come interagire con std::shared_ptr

boost::thread t(std::mem_fn(&foo::boo), fptr);

+0

Eccellente che funziona bene! grazie. –

3

Un'alternativa alla risposta di Dave S è quello di definire questo (prima<boost/mem_fn.hpp> viene incluso):

namespace boost 
{ 
    template<typename T> 
    inline T* 
    get_pointer(const std::shared_ptr<T>& p) 
    { return p.get(); } 
} 

che "educa" boost::mem_fn per ottenere un puntatore raw da std::shared_ptr.

In C++ 11 std::mem_fn è richiesto per lavorare con qualsiasi tipo puntatore-like, semplicemente deferenziandolo cioè *fptr, ma boost::mem_fn usa invece *boost::get_pointer(fptr). Non so se è stato risolto nell'ultima versione di Boost, ma direi che dovrebbe utilizzare SFINAE per rilevare se il get_pointer funzionerà, e dovrebbe semplicemente dereferenziarlo altrimenti.