Reputation: 672
I have the following two code segments. The first block compiles and works as expected. However the second block does not compile.
My question is, given the code below what is the correct syntax when trying to create a thread based on an instance of an object that is being proxied by a 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;
}
The compiler error:
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
Upvotes: 5
Views: 3252
Reputation: 171443
An alternative to Dave S's answer is to define this (before <boost/mem_fn.hpp>
gets included):
namespace boost
{
template<typename T>
inline T*
get_pointer(const std::shared_ptr<T>& p)
{ return p.get(); }
}
That "teaches" boost::mem_fn
to obtain a raw pointer from a std::shared_ptr
.
In C++11 std::mem_fn
is required to work with any pointer-like type, simply by dereferencing it i.e. *fptr
, but boost::mem_fn
instead uses *boost::get_pointer(fptr)
. I don't know if it's fixed in the latest version of Boost, but I would argue that it should use SFINAE to detect whether get_pointer
will work, and should just dereference it otherwise.
Upvotes: 3
Reputation: 21123
The problem is that boost::thread
relies on boost::mem_fn
to handle member functions, and boost::mem_fn
(or at least the version you are using) doesn't know how to use a std::shared_ptr
to invoke a member function as it expects you to use boost::shared_ptr
or one of the myriad of other smart pointer types in your error listing.
The raw pointer works because boost::mem_fn
already has that overload. The solutions are to use boost::shared_ptr
or std::mem_fn
. The latter works because std::mem_fn
knows how to interact with std::shared_ptr
boost::thread t(std::mem_fn(&foo::boo), fptr);
Upvotes: 9