/* Copyright 2005 Alo Sarv * Distributed under the Boost Software Licence, Version 1.0 * (See accompanying file LICENCE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ #include #include #include #include #include namespace detail { template struct unchainptr_impl { // non-const overloads Class& operator()(Class &x) const { return x; } template Class& operator()(ChainedPtr &x) const { return operator()(*x); } Class& operator()(boost::reference_wrapper &x) const { return operator()(x.get()); } }; template struct unchainptr_const_impl { // const overloads const Class& operator()(const Class &x) const { return x; } template const Class& operator()(const ChainedPtr &x) const { return operator()(*x); } const Class& operator()( const boost::reference_wrapper &x ) const { return operator()(x.get()); } }; template struct get_type { typedef T type; }; template struct get_type { typedef typename get_type::type type; }; template struct get_type { typedef typename get_type::type type; }; template struct get_type { typedef typename get_type::type type; }; template struct get_type > { typedef typename get_type::type type; }; template struct get_type > { typedef typename get_type::type type; }; template struct get_type > { typedef typename get_type::type type; }; } // end namespace detail /** * Unchains any pointer (even smart and nested) type, and returns a reference * to the real type. Const-correctness is preserved, thus passing a pointer to * const object and expecting non-const reference in return is an error. * * @param ptr Pointer expected to be unchained. Non-pointers are returned * unmodified. * @returns Class& or const Class&, depending on input parameters. */ template inline typename detail::get_type::type& unchain_ptr(ChainedPtr ptr) { return typename boost::mpl::if_< boost::is_const, detail::unchainptr_const_impl< typename detail::get_type::type >, detail::unchainptr_impl< typename detail::get_type::type > >::type()(ptr); }