Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Pablo Halpern 2009. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@101: // (C) Copyright Ion Gaztanaga 2011-2014. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/intrusive for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTRUSIVE_POINTER_TRAITS_HPP Chris@16: #define BOOST_INTRUSIVE_POINTER_TRAITS_HPP Chris@16: Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: #include Chris@101: Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: namespace boost { Chris@16: namespace intrusive { Chris@101: namespace detail { Chris@101: Chris@101: #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1310) Chris@101: BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to) Chris@101: BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from) Chris@101: BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from) Chris@101: BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from) Chris@101: #else Chris@101: BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to) Chris@101: BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from) Chris@101: BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from) Chris@101: BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from) Chris@101: #endif Chris@101: Chris@101: BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(element_type) Chris@101: BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type) Chris@101: BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) Chris@101: BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr) Chris@101: Chris@101: } //namespace detail { Chris@101: Chris@16: Chris@16: //! pointer_traits is the implementation of C++11 std::pointer_traits class with some Chris@16: //! extensions like castings. Chris@16: //! Chris@16: //! pointer_traits supplies a uniform interface to certain attributes of pointer-like types. Chris@101: //! Chris@101: //! Note: When defining a custom family of pointers or references to be used with BI Chris@101: //! library, make sure the public static conversion functions accessed through Chris@101: //! the `pointer_traits` interface (`*_cast_from` and `pointer_to`) can Chris@101: //! properly convert between const and nonconst referred member types Chris@101: //! without the use of implicit constructor calls. It is suggested these Chris@101: //! conversions be implemented as function templates, where the template Chris@101: //! argument is the type of the object being converted from. Chris@16: template Chris@16: struct pointer_traits Chris@16: { Chris@16: #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED Chris@16: //!The pointer type Chris@16: //!queried by this pointer_traits instantiation Chris@16: typedef Ptr pointer; Chris@16: Chris@16: //!Ptr::element_type if such a type exists; otherwise, T if Ptr is a class Chris@16: //!template instantiation of the form SomePointer, where Args is zero or Chris@16: //!more type arguments ; otherwise , the specialization is ill-formed. Chris@16: typedef unspecified_type element_type; Chris@16: Chris@16: //!Ptr::difference_type if such a type exists; otherwise, Chris@16: //!std::ptrdiff_t. Chris@16: typedef unspecified_type difference_type; Chris@16: Chris@16: //!Ptr::rebind if such a type exists; otherwise, SomePointer if Ptr is Chris@16: //!a class template instantiation of the form SomePointer, where Args is zero or Chris@16: //!more type arguments ; otherwise, the instantiation of rebind is ill-formed. Chris@16: //! Chris@16: //!For portable code for C++03 and C++11,
typename rebind_pointer::type
Chris@16: //!shall be used instead of rebind to obtain a pointer to U. Chris@16: template using rebind = unspecified; Chris@16: Chris@101: //!Ptr::reference if such a type exists (non-standard extension); otherwise, element_type & Chris@16: //! Chris@101: typedef unspecified_type reference; Chris@16: #else Chris@16: typedef Ptr pointer; Chris@16: // Chris@16: typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT Chris@16: ( boost::intrusive::detail::, Ptr, element_type Chris@16: , boost::intrusive::detail::first_param) element_type; Chris@16: // Chris@16: typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT Chris@16: (boost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type; Chris@101: Chris@101: typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT Chris@101: (boost::intrusive::detail::, Ptr, reference, typename boost::intrusive::detail::unvoid_ref::type) reference; Chris@16: // Chris@16: template struct rebind_pointer Chris@16: { Chris@101: typedef typename boost::intrusive::pointer_rebind::type type; Chris@16: }; Chris@16: Chris@16: #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) Chris@101: template using rebind = typename boost::intrusive::pointer_rebind::type; Chris@16: #endif Chris@16: #endif //#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) Chris@16: Chris@16: //! Remark: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise, Chris@16: //! it is element_type &. Chris@16: //! Chris@101: //! Returns: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(reference). Chris@16: //! Non-standard extension: If such function does not exist, returns pointer(addressof(r)); Chris@101: //! Chris@101: //! Note: For non-conforming compilers only the existence of a member function called Chris@101: //! pointer_to is checked. Chris@16: static pointer pointer_to(reference r) Chris@16: { Chris@16: //Non-standard extension, it does not require Ptr::pointer_to. If not present Chris@16: //tries to converts &r to pointer. Chris@16: const bool value = boost::intrusive::detail:: Chris@16: has_member_function_callable_with_pointer_to Chris@101: ::value; Chris@101: boost::intrusive::detail::bool_ flag; Chris@16: return pointer_traits::priv_pointer_to(flag, r); Chris@16: } Chris@16: Chris@16: //! Remark: Non-standard extension. Chris@16: //! Chris@101: //! Returns: A dereferenceable pointer to r obtained by calling the static template function Chris@101: //! Ptr::static_cast_from(UPpr/const UPpr &). Chris@16: //! If such function does not exist, returns pointer_to(static_cast(*uptr)) Chris@101: //! Chris@101: //! Note: For non-conforming compilers only the existence of a member function called Chris@101: //! static_cast_from is checked. Chris@16: template Chris@16: static pointer static_cast_from(const UPtr &uptr) Chris@16: { Chris@101: typedef const UPtr &RefArg; Chris@16: const bool value = boost::intrusive::detail:: Chris@16: has_member_function_callable_with_static_cast_from Chris@101: ::value Chris@101: || boost::intrusive::detail:: Chris@101: has_member_function_callable_with_static_cast_from Chris@101: ::value; Chris@101: return pointer_traits::priv_static_cast_from(boost::intrusive::detail::bool_(), uptr); Chris@16: } Chris@16: Chris@16: //! Remark: Non-standard extension. Chris@16: //! Chris@101: //! Returns: A dereferenceable pointer to r obtained by calling the static template function Chris@101: //! Ptr::const_cast_from(UPpr/const UPpr &). Chris@16: //! If such function does not exist, returns pointer_to(const_cast(*uptr)) Chris@101: //! Chris@101: //! Note: For non-conforming compilers only the existence of a member function called Chris@101: //! const_cast_from is checked. Chris@16: template Chris@16: static pointer const_cast_from(const UPtr &uptr) Chris@16: { Chris@101: typedef const UPtr &RefArg; Chris@16: const bool value = boost::intrusive::detail:: Chris@16: has_member_function_callable_with_const_cast_from Chris@101: ::value Chris@101: || boost::intrusive::detail:: Chris@101: has_member_function_callable_with_const_cast_from Chris@101: ::value; Chris@101: return pointer_traits::priv_const_cast_from(boost::intrusive::detail::bool_(), uptr); Chris@16: } Chris@16: Chris@16: //! Remark: Non-standard extension. Chris@16: //! Chris@101: //! Returns: A dereferenceable pointer to r obtained by calling the static template function Chris@101: //! Ptr::dynamic_cast_from(UPpr/const UPpr &). Chris@16: //! If such function does not exist, returns pointer_to(*dynamic_cast(&*uptr)) Chris@101: //! Chris@101: //! Note: For non-conforming compilers only the existence of a member function called Chris@101: //! dynamic_cast_from is checked. Chris@16: template Chris@16: static pointer dynamic_cast_from(const UPtr &uptr) Chris@16: { Chris@101: typedef const UPtr &RefArg; Chris@16: const bool value = boost::intrusive::detail:: Chris@16: has_member_function_callable_with_dynamic_cast_from Chris@101: ::value Chris@101: || boost::intrusive::detail:: Chris@101: has_member_function_callable_with_dynamic_cast_from Chris@101: ::value; Chris@101: return pointer_traits::priv_dynamic_cast_from(boost::intrusive::detail::bool_(), uptr); Chris@16: } Chris@16: Chris@16: ///@cond Chris@16: private: Chris@16: //priv_to_raw_pointer Chris@16: template Chris@16: static T* to_raw_pointer(T* p) Chris@16: { return p; } Chris@16: Chris@16: template Chris@16: static typename pointer_traits::element_type* Chris@16: to_raw_pointer(const Pointer &p) Chris@16: { return pointer_traits::to_raw_pointer(p.operator->()); } Chris@16: Chris@16: //priv_pointer_to Chris@101: static pointer priv_pointer_to(boost::intrusive::detail::true_, reference r) Chris@101: { return Ptr::pointer_to(r); } Chris@16: Chris@101: static pointer priv_pointer_to(boost::intrusive::detail::false_, reference r) Chris@101: { return pointer(boost::intrusive::detail::addressof(r)); } Chris@16: Chris@16: //priv_static_cast_from Chris@16: template Chris@101: static pointer priv_static_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) Chris@16: { return Ptr::static_cast_from(uptr); } Chris@16: Chris@16: template Chris@101: static pointer priv_static_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) Chris@16: { return pointer_to(*static_cast(to_raw_pointer(uptr))); } Chris@16: Chris@16: //priv_const_cast_from Chris@16: template Chris@101: static pointer priv_const_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) Chris@16: { return Ptr::const_cast_from(uptr); } Chris@16: Chris@16: template Chris@101: static pointer priv_const_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) Chris@16: { return pointer_to(const_cast(*uptr)); } Chris@16: Chris@16: //priv_dynamic_cast_from Chris@16: template Chris@101: static pointer priv_dynamic_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) Chris@16: { return Ptr::dynamic_cast_from(uptr); } Chris@16: Chris@16: template Chris@101: static pointer priv_dynamic_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) Chris@101: { Chris@101: element_type *p = dynamic_cast(&*uptr); Chris@101: if(!p){ Chris@101: return pointer(); Chris@101: } Chris@101: else{ Chris@101: return pointer_to(*p); Chris@101: } Chris@101: } Chris@16: ///@endcond Chris@16: }; Chris@16: Chris@16: ///@cond Chris@16: Chris@16: // Remove cv qualification from Ptr parameter to pointer_traits: Chris@16: template Chris@16: struct pointer_traits : pointer_traits {}; Chris@16: template Chris@16: struct pointer_traits : pointer_traits { }; Chris@16: template Chris@16: struct pointer_traits : pointer_traits { }; Chris@16: // Remove reference from Ptr parameter to pointer_traits: Chris@16: template Chris@16: struct pointer_traits : pointer_traits { }; Chris@16: Chris@16: ///@endcond Chris@16: Chris@16: //! Specialization of pointer_traits for raw pointers Chris@16: //! Chris@16: template Chris@16: struct pointer_traits Chris@16: { Chris@16: typedef T element_type; Chris@16: typedef T* pointer; Chris@16: typedef std::ptrdiff_t difference_type; Chris@16: Chris@16: #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED Chris@16: typedef T & reference; Chris@16: //!typedef for
U *
Chris@16: //! Chris@16: //!For portable code for C++03 and C++11,
typename rebind_pointer::type
Chris@16: //!shall be used instead of rebind to obtain a pointer to U. Chris@16: template using rebind = U*; Chris@16: #else Chris@16: typedef typename boost::intrusive::detail::unvoid_ref::type reference; Chris@16: #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) Chris@16: template using rebind = U*; Chris@16: #endif Chris@16: #endif Chris@16: Chris@16: template struct rebind_pointer Chris@16: { typedef U* type; }; Chris@16: Chris@16: //! Returns: addressof(r) Chris@16: //! Chris@16: static pointer pointer_to(reference r) Chris@16: { return boost::intrusive::detail::addressof(r); } Chris@16: Chris@16: //! Returns: static_cast(uptr) Chris@16: //! Chris@16: template Chris@16: static pointer static_cast_from(U *uptr) Chris@16: { return static_cast(uptr); } Chris@16: Chris@16: //! Returns: const_cast(uptr) Chris@16: //! Chris@16: template Chris@16: static pointer const_cast_from(U *uptr) Chris@16: { return const_cast(uptr); } Chris@16: Chris@16: //! Returns: dynamic_cast(uptr) Chris@16: //! Chris@16: template Chris@16: static pointer dynamic_cast_from(U *uptr) Chris@16: { return dynamic_cast(uptr); } Chris@16: }; Chris@16: Chris@16: } //namespace container { Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP)