1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Pablo Halpern 2009. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 ////////////////////////////////////////////////////////////////////////////// 8 // 9 // (C) Copyright Ion Gaztanaga 2011-2014. Distributed under the Boost 10 // Software License, Version 1.0. (See accompanying file 11 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 // 13 // See http://www.boost.org/libs/intrusive for documentation. 14 // 15 ////////////////////////////////////////////////////////////////////////////// 16 17 #ifndef BOOST_INTRUSIVE_POINTER_TRAITS_HPP 18 #define BOOST_INTRUSIVE_POINTER_TRAITS_HPP 19 20 #include <boost/intrusive/detail/config_begin.hpp> 21 #include <boost/intrusive/detail/workaround.hpp> 22 #include <boost/intrusive/pointer_rebind.hpp> 23 #include <boost/move/detail/pointer_element.hpp> 24 #include <boost/intrusive/detail/mpl.hpp> 25 #include <cstddef> 26 27 #if defined(BOOST_HAS_PRAGMA_ONCE) 28 # pragma once 29 #endif 30 31 namespace boost { 32 namespace intrusive { 33 namespace detail { 34 35 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1310) 36 BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to) 37 BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from) 38 BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from) 39 BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from) 40 #else 41 BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to) 42 BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from) 43 BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from) 44 BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from) 45 #endif 46 47 BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(element_type) 48 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type) 49 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) 50 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr) 51 52 } //namespace detail { 53 54 55 //! pointer_traits is the implementation of C++11 std::pointer_traits class with some 56 //! extensions like castings. 57 //! 58 //! pointer_traits supplies a uniform interface to certain attributes of pointer-like types. 59 //! 60 //! <b>Note</b>: When defining a custom family of pointers or references to be used with BI 61 //! library, make sure the public static conversion functions accessed through 62 //! the `pointer_traits` interface (`*_cast_from` and `pointer_to`) can 63 //! properly convert between const and nonconst referred member types 64 //! <b>without the use of implicit constructor calls</b>. It is suggested these 65 //! conversions be implemented as function templates, where the template 66 //! argument is the type of the object being converted from. 67 template <typename Ptr> 68 struct pointer_traits 69 { 70 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED 71 //!The pointer type 72 //!queried by this pointer_traits instantiation 73 typedef Ptr pointer; 74 75 //!Ptr::element_type if such a type exists; otherwise, T if Ptr is a class 76 //!template instantiation of the form SomePointer<T, Args>, where Args is zero or 77 //!more type arguments ; otherwise , the specialization is ill-formed. 78 typedef unspecified_type element_type; 79 80 //!Ptr::difference_type if such a type exists; otherwise, 81 //!std::ptrdiff_t. 82 typedef unspecified_type difference_type; 83 84 //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is 85 //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or 86 //!more type arguments ; otherwise, the instantiation of rebind is ill-formed. 87 //! 88 //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre> 89 //!shall be used instead of rebind<U> to obtain a pointer to U. 90 template <class U> using rebind = unspecified; 91 92 //!Ptr::reference if such a type exists (non-standard extension); otherwise, element_type & 93 //! 94 typedef unspecified_type reference; 95 #else 96 typedef Ptr pointer; 97 // 98 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT 99 ( boost::intrusive::detail::, Ptr, element_type 100 , boost::movelib::detail::first_param<Ptr>) element_type; 101 // 102 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT 103 (boost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type; 104 105 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT 106 (boost::intrusive::detail::, Ptr, reference, typename boost::intrusive::detail::unvoid_ref<element_type>::type) reference; 107 // 108 template <class U> struct rebind_pointer 109 { 110 typedef typename boost::intrusive::pointer_rebind<Ptr, U>::type type; 111 }; 112 113 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 114 template <class U> using rebind = typename boost::intrusive::pointer_rebind<Ptr, U>::type; 115 #endif 116 #endif //#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 117 118 //! <b>Remark</b>: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise, 119 //! it is element_type &. 120 //! 121 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(reference). 122 //! Non-standard extension: If such function does not exist, returns pointer(addressof(r)); 123 //! 124 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 125 //! <code>pointer_to</code> is checked. pointer_toboost::intrusive::pointer_traits126 BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r) 127 { 128 //Non-standard extension, it does not require Ptr::pointer_to. If not present 129 //tries to converts &r to pointer. 130 const bool value = boost::intrusive::detail:: 131 has_member_function_callable_with_pointer_to 132 <Ptr, Ptr (*)(reference)>::value; 133 boost::intrusive::detail::bool_<value> flag; 134 return pointer_traits::priv_pointer_to(flag, r); 135 } 136 137 //! <b>Remark</b>: Non-standard extension. 138 //! 139 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function 140 //! Ptr::static_cast_from(UPpr/const UPpr &). 141 //! If such function does not exist, returns pointer_to(static_cast<element_type&>(*uptr)) 142 //! 143 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 144 //! <code>static_cast_from</code> is checked. 145 template<class UPtr> static_cast_fromboost::intrusive::pointer_traits146 BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(const UPtr &uptr) 147 { 148 typedef const UPtr &RefArg; 149 const bool value = boost::intrusive::detail:: 150 has_member_function_callable_with_static_cast_from 151 <pointer, pointer(*)(RefArg)>::value 152 || boost::intrusive::detail:: 153 has_member_function_callable_with_static_cast_from 154 <pointer, pointer(*)(UPtr)>::value; 155 return pointer_traits::priv_static_cast_from(boost::intrusive::detail::bool_<value>(), uptr); 156 } 157 158 //! <b>Remark</b>: Non-standard extension. 159 //! 160 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function 161 //! Ptr::const_cast_from<UPtr>(UPpr/const UPpr &). 162 //! If such function does not exist, returns pointer_to(const_cast<element_type&>(*uptr)) 163 //! 164 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 165 //! <code>const_cast_from</code> is checked. 166 template<class UPtr> const_cast_fromboost::intrusive::pointer_traits167 BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(const UPtr &uptr) 168 { 169 typedef const UPtr &RefArg; 170 const bool value = boost::intrusive::detail:: 171 has_member_function_callable_with_const_cast_from 172 <pointer, pointer(*)(RefArg)>::value 173 || boost::intrusive::detail:: 174 has_member_function_callable_with_const_cast_from 175 <pointer, pointer(*)(UPtr)>::value; 176 return pointer_traits::priv_const_cast_from(boost::intrusive::detail::bool_<value>(), uptr); 177 } 178 179 //! <b>Remark</b>: Non-standard extension. 180 //! 181 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function 182 //! Ptr::dynamic_cast_from<UPtr>(UPpr/const UPpr &). 183 //! If such function does not exist, returns pointer_to(*dynamic_cast<element_type*>(&*uptr)) 184 //! 185 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 186 //! <code>dynamic_cast_from</code> is checked. 187 template<class UPtr> dynamic_cast_fromboost::intrusive::pointer_traits188 BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(const UPtr &uptr) 189 { 190 typedef const UPtr &RefArg; 191 const bool value = boost::intrusive::detail:: 192 has_member_function_callable_with_dynamic_cast_from 193 <pointer, pointer(*)(RefArg)>::value 194 || boost::intrusive::detail:: 195 has_member_function_callable_with_dynamic_cast_from 196 <pointer, pointer(*)(UPtr)>::value; 197 return pointer_traits::priv_dynamic_cast_from(boost::intrusive::detail::bool_<value>(), uptr); 198 } 199 200 ///@cond 201 private: 202 //priv_to_raw_pointer 203 template <class T> to_raw_pointerboost::intrusive::pointer_traits204 BOOST_INTRUSIVE_FORCEINLINE static T* to_raw_pointer(T* p) 205 { return p; } 206 207 template <class Pointer> 208 BOOST_INTRUSIVE_FORCEINLINE static typename pointer_traits<Pointer>::element_type* to_raw_pointerboost::intrusive::pointer_traits209 to_raw_pointer(const Pointer &p) 210 { return pointer_traits::to_raw_pointer(p.operator->()); } 211 212 //priv_pointer_to priv_pointer_toboost::intrusive::pointer_traits213 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_pointer_to(boost::intrusive::detail::true_, reference r) 214 { return Ptr::pointer_to(r); } 215 priv_pointer_toboost::intrusive::pointer_traits216 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_pointer_to(boost::intrusive::detail::false_, reference r) 217 { return pointer(boost::intrusive::detail::addressof(r)); } 218 219 //priv_static_cast_from 220 template<class UPtr> priv_static_cast_fromboost::intrusive::pointer_traits221 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_static_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) 222 { return Ptr::static_cast_from(uptr); } 223 224 template<class UPtr> priv_static_cast_fromboost::intrusive::pointer_traits225 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_static_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) 226 { return uptr ? pointer_to(*static_cast<element_type*>(to_raw_pointer(uptr))) : pointer(); } 227 228 //priv_const_cast_from 229 template<class UPtr> priv_const_cast_fromboost::intrusive::pointer_traits230 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_const_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) 231 { return Ptr::const_cast_from(uptr); } 232 233 template<class UPtr> priv_const_cast_fromboost::intrusive::pointer_traits234 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_const_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) 235 { return uptr ? pointer_to(const_cast<element_type&>(*uptr)) : pointer(); } 236 237 //priv_dynamic_cast_from 238 template<class UPtr> priv_dynamic_cast_fromboost::intrusive::pointer_traits239 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_dynamic_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) 240 { return Ptr::dynamic_cast_from(uptr); } 241 242 template<class UPtr> priv_dynamic_cast_fromboost::intrusive::pointer_traits243 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_dynamic_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) 244 { return uptr ? pointer_to(dynamic_cast<element_type&>(*uptr)) : pointer(); } 245 ///@endcond 246 }; 247 248 ///@cond 249 250 // Remove cv qualification from Ptr parameter to pointer_traits: 251 template <typename Ptr> 252 struct pointer_traits<const Ptr> : pointer_traits<Ptr> {}; 253 template <typename Ptr> 254 struct pointer_traits<volatile Ptr> : pointer_traits<Ptr> { }; 255 template <typename Ptr> 256 struct pointer_traits<const volatile Ptr> : pointer_traits<Ptr> { }; 257 // Remove reference from Ptr parameter to pointer_traits: 258 template <typename Ptr> 259 struct pointer_traits<Ptr&> : pointer_traits<Ptr> { }; 260 261 ///@endcond 262 263 //! Specialization of pointer_traits for raw pointers 264 //! 265 template <typename T> 266 struct pointer_traits<T*> 267 { 268 typedef T element_type; 269 typedef T* pointer; 270 typedef std::ptrdiff_t difference_type; 271 272 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED 273 typedef T & reference; 274 //!typedef for <pre>U *</pre> 275 //! 276 //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre> 277 //!shall be used instead of rebind<U> to obtain a pointer to U. 278 template <class U> using rebind = U*; 279 #else 280 typedef typename boost::intrusive::detail::unvoid_ref<element_type>::type reference; 281 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 282 template <class U> using rebind = U*; 283 #endif 284 #endif 285 286 template <class U> struct rebind_pointer 287 { typedef U* type; }; 288 289 //! <b>Returns</b>: addressof(r) 290 //! pointer_toboost::intrusive::pointer_traits291 BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r) 292 { return boost::intrusive::detail::addressof(r); } 293 294 //! <b>Returns</b>: static_cast<pointer>(uptr) 295 //! 296 template<class U> static_cast_fromboost::intrusive::pointer_traits297 BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(U *uptr) 298 { return static_cast<pointer>(uptr); } 299 300 //! <b>Returns</b>: const_cast<pointer>(uptr) 301 //! 302 template<class U> const_cast_fromboost::intrusive::pointer_traits303 BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(U *uptr) 304 { return const_cast<pointer>(uptr); } 305 306 //! <b>Returns</b>: dynamic_cast<pointer>(uptr) 307 //! 308 template<class U> dynamic_cast_fromboost::intrusive::pointer_traits309 BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(U *uptr) 310 { return dynamic_cast<pointer>(uptr); } 311 }; 312 313 } //namespace container { 314 } //namespace boost { 315 316 #include <boost/intrusive/detail/config_end.hpp> 317 318 #endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP) 319