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.