[Boost-bugs] [Boost C++ Libraries] #3840: Boost.Intrusive conflicts with Boost.Bind + smart pointers

Subject: [Boost-bugs] [Boost C++ Libraries] #3840: Boost.Intrusive conflicts with Boost.Bind + smart pointers
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2010-01-14 12:15:00


#3840: Boost.Intrusive conflicts with Boost.Bind + smart pointers
-----------------------------------------------+----------------------------
 Reporter: andysem | Owner: igaztanaga
     Type: Bugs | Status: new
Milestone: Boost 1.42.0 | Component: intrusive
  Version: Boost 1.41.0 | Severity: Problem
 Keywords: get_pointer bind mem_fn intrusive |
-----------------------------------------------+----------------------------
 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.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/3840>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:02 UTC