Opened 13 years ago
Closed 12 years ago
#3840 closed Bugs (fixed)
Boost.Intrusive conflicts with Boost.Bind + smart pointers
| Reported by: | Andrey Semashev | Owned by: | Ion Gaztañaga |
|---|---|---|---|
| Milestone: | Boost 1.45.0 | Component: | intrusive |
| Version: | Boost 1.41.0 | Severity: | Problem |
| Keywords: | get_pointer bind mem_fn intrusive | Cc: |
Description
The file intrusive/detail/utilities.hpp defines generic get_pointer function. Apparently, this function is in conflict with the same-named functions for smart pointers, such as intrusive_ptr, which breaks compilation of boost::bind. The following example shows the problem:
#include <boost/bind.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/intrusive/list.hpp>
namespace intrusive = boost::intrusive;
typedef intrusive::list_base_hook<
intrusive::link_mode< intrusive::auto_unlink >,
intrusive::tag< struct MyStructTag >
> ListHook_t;
struct MyStruct :
public ListHook_t
{
void foo() {}
friend void intrusive_ptr_add_ref(MyStruct*) {}
friend void intrusive_ptr_release(MyStruct*) {}
};
typedef intrusive::list<
MyStruct,
intrusive::base_hook< ListHook_t >,
intrusive::constant_time_size< false >
> List_t;
int main(int, char*[])
{
List_t structs;
boost::intrusive_ptr< MyStruct > p = new MyStruct();
structs.push_back(*p);
boost::bind(&MyStruct::foo, p)();
return 0;
}
The compilation fails at least with MSVC 7.1 and GCC 4.1.0, the error is as follows:
./ThirdParty/BOOST/boost/intrusive/detail/utilities.hpp: In instantiation of 'boost::intrusive::detail::smart_ptr_type<boost::intrusive_ptr<MyStruct> >': ./ThirdParty/BOOST/boost/bind/mem_fn_template.hpp:40: instantiated from 'R boost::_mfi::mf0<R, T>::call(U&, const void*) const [with U = boost::intrusive_ptr<MyStruct>, R = void, T = MyStruct]' ./ThirdParty/BOOST/boost/bind/mem_fn_template.hpp:54: instantiated from 'R boost::_mfi::mf0<R, T>::operator()(U&) const [with U = boost::intrusive_ptr<MyStruct>, R = void, T = MyStruct]' ./ThirdParty/BOOST/boost/bind/bind.hpp:246: instantiated from 'void boost::_bi::list1<A1>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf0<void, MyStruct>, A = boost::_bi::list0, A1 = boost::_bi::value<boost::intrusive_ptr<MyStruct> >]' ./ThirdParty/BOOST/boost/bind/bind_template.hpp:20: instantiated from 'typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf0<void, MyStruct>, L = boost::_bi::list1<boost::_bi::value<boost::intrusive_ptr<MyStruct> > >]' 1.cpp:33: instantiated from here ./ThirdParty/BOOST/boost/intrusive/detail/utilities.hpp:113: error: no type named 'value_type' in 'class boost::intrusive_ptr<MyStruct>' ./ThirdParty/BOOST/boost/intrusive/detail/utilities.hpp:114: error: no type named 'value_type' in 'class boost::intrusive_ptr<MyStruct>' ./ThirdParty/BOOST/boost/intrusive/detail/utilities.hpp:115: error: no type named 'value_type' in 'class boost::intrusive_ptr<MyStruct>'
One side of the problem is that smart_ptr_type trait, which is used by get_pointer from Boost.Intrusive, incorrectly detects pointee type. It assumes the smart pointer has a value_type nested typedef, while the conventional typedef is element_type. I would suggest using pointee trait from pointee.hpp to get this type portably.
The other side of the problem is that get_pointer from Boost.Intrusive should not have been used by Boost.Bind in the first place, because it's defined in the private namespace boost::intrusive::detail. I guess, this happens because of some ADL-related problem. Perhaps there is a using directive somewhere that leads to this.
One possible solution of the problem is to simply remove get_pointer definition from Boost.Intrusive and use unqualified calls to get_pointer instead. The version of get_pointer for raw pointers is already available in the get_pointer.hpp header.
Attachments (1)
Change History (5)
comment:1 by , 13 years ago
by , 13 years ago
| Attachment: | get_ptr_fix.patch added |
|---|
The patch renames get_pointer function from Boost.Intrusive
comment:2 by , 13 years ago
Oh, I think I know why get_pointer from Boost.Intrusive was found. ListHook_t in my example derives from detail::generic_hook, which brings in the detail namespace into lookup.
comment:3 by , 13 years ago
I generally use compile-fail test cases like [source:/trunk/libs/units/test/fail_adl_detail.cpp@46171 fail_adl_detail.cpp] to make sure that ADL isn't going awry.
comment:4 by , 12 years ago
| Milestone: | Boost 1.42.0 → Boost-1.45.0 |
|---|---|
| Resolution: | → fixed |
| Status: | new → closed |
Fixed for Boost 1.45 in release branch

As my local way of fixing the problem, I renamed the get_pointer from Boost.Intrusive and all references to it. Please, find the patch attached.