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(size_type) 50 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) 51 BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr) 52 53 } //namespace detail { 54 55 56 //! pointer_traits is the implementation of C++11 std::pointer_traits class with some 57 //! extensions like castings. 58 //! 59 //! pointer_traits supplies a uniform interface to certain attributes of pointer-like types. 60 //! 61 //! <b>Note</b>: When defining a custom family of pointers or references to be used with BI 62 //! library, make sure the public static conversion functions accessed through 63 //! the `pointer_traits` interface (`*_cast_from` and `pointer_to`) can 64 //! properly convert between const and nonconst referred member types 65 //! <b>without the use of implicit constructor calls</b>. It is suggested these 66 //! conversions be implemented as function templates, where the template 67 //! argument is the type of the object being converted from. 68 template <typename Ptr> 69 struct pointer_traits 70 { 71 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED 72 //!The pointer type 73 //!queried by this pointer_traits instantiation 74 typedef Ptr pointer; 75 76 //!Ptr::element_type if such a type exists; otherwise, T if Ptr is a class 77 //!template instantiation of the form SomePointer<T, Args>, where Args is zero or 78 //!more type arguments ; otherwise , the specialization is ill-formed. 79 typedef unspecified_type element_type; 80 81 //!Ptr::difference_type if such a type exists; otherwise, 82 //!std::ptrdiff_t. 83 typedef unspecified_type difference_type; 84 85 //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is 86 //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or 87 //!more type arguments ; otherwise, the instantiation of rebind is ill-formed. 88 //! 89 //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre> 90 //!shall be used instead of rebind<U> to obtain a pointer to U. 91 template <class U> using rebind = unspecified; 92 93 //!Ptr::reference if such a type exists (non-standard extension); otherwise, element_type & 94 //! 95 typedef unspecified_type reference; 96 #else 97 typedef Ptr pointer; 98 // 99 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT 100 ( boost::intrusive::detail::, Ptr, element_type 101 , boost::movelib::detail::first_param<Ptr>) element_type; 102 // 103 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT 104 (boost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type; 105 106 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT 107 ( boost::intrusive::detail::, Ptr, size_type 108 , typename boost::move_detail:: 109 make_unsigned<difference_type>::type) size_type; 110 111 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT 112 ( boost::intrusive::detail::, Ptr, reference 113 , typename boost::intrusive::detail::unvoid_ref<element_type>::type) reference; 114 // 115 template <class U> struct rebind_pointer 116 { 117 typedef typename boost::intrusive::pointer_rebind<Ptr, U>::type type; 118 }; 119 120 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 121 template <class U> using rebind = typename boost::intrusive::pointer_rebind<Ptr, U>::type; 122 #endif 123 #endif //#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 124 125 //! <b>Remark</b>: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise, 126 //! it is element_type &. 127 //! 128 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(reference). 129 //! Non-standard extension: If such function does not exist, returns pointer(addressof(r)); 130 //! 131 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 132 //! <code>pointer_to</code> is checked. pointer_toboost::intrusive::pointer_traits133 BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r) BOOST_NOEXCEPT 134 { 135 //Non-standard extension, it does not require Ptr::pointer_to. If not present 136 //tries to converts &r to pointer. 137 const bool value = boost::intrusive::detail:: 138 has_member_function_callable_with_pointer_to 139 <Ptr, Ptr (*)(reference)>::value; 140 boost::intrusive::detail::bool_<value> flag; 141 return pointer_traits::priv_pointer_to(flag, r); 142 } 143 144 //! <b>Remark</b>: Non-standard extension. 145 //! 146 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function 147 //! Ptr::static_cast_from(UPpr/const UPpr &). 148 //! If such function does not exist, returns pointer_to(static_cast<element_type&>(*uptr)) 149 //! 150 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 151 //! <code>static_cast_from</code> is checked. 152 template<class UPtr> static_cast_fromboost::intrusive::pointer_traits153 BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(const UPtr &uptr) BOOST_NOEXCEPT 154 { 155 typedef const UPtr &RefArg; 156 const bool value = boost::intrusive::detail:: 157 has_member_function_callable_with_static_cast_from 158 <pointer, pointer(*)(RefArg)>::value 159 || boost::intrusive::detail:: 160 has_member_function_callable_with_static_cast_from 161 <pointer, pointer(*)(UPtr)>::value; 162 return pointer_traits::priv_static_cast_from(boost::intrusive::detail::bool_<value>(), uptr); 163 } 164 165 //! <b>Remark</b>: Non-standard extension. 166 //! 167 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function 168 //! Ptr::const_cast_from<UPtr>(UPpr/const UPpr &). 169 //! If such function does not exist, returns pointer_to(const_cast<element_type&>(*uptr)) 170 //! 171 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 172 //! <code>const_cast_from</code> is checked. 173 template<class UPtr> const_cast_fromboost::intrusive::pointer_traits174 BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(const UPtr &uptr) BOOST_NOEXCEPT 175 { 176 typedef const UPtr &RefArg; 177 const bool value = boost::intrusive::detail:: 178 has_member_function_callable_with_const_cast_from 179 <pointer, pointer(*)(RefArg)>::value 180 || boost::intrusive::detail:: 181 has_member_function_callable_with_const_cast_from 182 <pointer, pointer(*)(UPtr)>::value; 183 return pointer_traits::priv_const_cast_from(boost::intrusive::detail::bool_<value>(), uptr); 184 } 185 186 //! <b>Remark</b>: Non-standard extension. 187 //! 188 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function 189 //! Ptr::dynamic_cast_from<UPtr>(UPpr/const UPpr &). 190 //! If such function does not exist, returns pointer_to(*dynamic_cast<element_type*>(&*uptr)) 191 //! 192 //! <b>Note</b>: For non-conforming compilers only the existence of a member function called 193 //! <code>dynamic_cast_from</code> is checked. 194 template<class UPtr> dynamic_cast_fromboost::intrusive::pointer_traits195 BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(const UPtr &uptr) BOOST_NOEXCEPT 196 { 197 typedef const UPtr &RefArg; 198 const bool value = boost::intrusive::detail:: 199 has_member_function_callable_with_dynamic_cast_from 200 <pointer, pointer(*)(RefArg)>::value 201 || boost::intrusive::detail:: 202 has_member_function_callable_with_dynamic_cast_from 203 <pointer, pointer(*)(UPtr)>::value; 204 return pointer_traits::priv_dynamic_cast_from(boost::intrusive::detail::bool_<value>(), uptr); 205 } 206 207 ///@cond 208 private: 209 //priv_to_raw_pointer 210 template <class T> to_raw_pointerboost::intrusive::pointer_traits211 BOOST_INTRUSIVE_FORCEINLINE static T* to_raw_pointer(T* p) BOOST_NOEXCEPT 212 { return p; } 213 214 template <class Pointer> 215 BOOST_INTRUSIVE_FORCEINLINE static typename pointer_traits<Pointer>::element_type* to_raw_pointerboost::intrusive::pointer_traits216 to_raw_pointer(const Pointer &p) BOOST_NOEXCEPT 217 { return pointer_traits::to_raw_pointer(p.operator->()); } 218 219 //priv_pointer_to priv_pointer_toboost::intrusive::pointer_traits220 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_pointer_to(boost::intrusive::detail::true_, reference r) BOOST_NOEXCEPT 221 { return Ptr::pointer_to(r); } 222 priv_pointer_toboost::intrusive::pointer_traits223 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_pointer_to(boost::intrusive::detail::false_, reference r) BOOST_NOEXCEPT 224 { return pointer(boost::intrusive::detail::addressof(r)); } 225 226 //priv_static_cast_from 227 template<class UPtr> priv_static_cast_fromboost::intrusive::pointer_traits228 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_static_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) BOOST_NOEXCEPT 229 { return Ptr::static_cast_from(uptr); } 230 231 template<class UPtr> priv_static_cast_fromboost::intrusive::pointer_traits232 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_static_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) BOOST_NOEXCEPT 233 { return uptr ? pointer_to(*static_cast<element_type*>(to_raw_pointer(uptr))) : pointer(); } 234 235 //priv_const_cast_from 236 template<class UPtr> priv_const_cast_fromboost::intrusive::pointer_traits237 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_const_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) BOOST_NOEXCEPT 238 { return Ptr::const_cast_from(uptr); } 239 240 template<class UPtr> priv_const_cast_fromboost::intrusive::pointer_traits241 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_const_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) BOOST_NOEXCEPT 242 { return uptr ? pointer_to(const_cast<element_type&>(*uptr)) : pointer(); } 243 244 //priv_dynamic_cast_from 245 template<class UPtr> priv_dynamic_cast_fromboost::intrusive::pointer_traits246 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_dynamic_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) BOOST_NOEXCEPT 247 { return Ptr::dynamic_cast_from(uptr); } 248 249 template<class UPtr> priv_dynamic_cast_fromboost::intrusive::pointer_traits250 BOOST_INTRUSIVE_FORCEINLINE static pointer priv_dynamic_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) BOOST_NOEXCEPT 251 { return uptr ? pointer_to(dynamic_cast<element_type&>(*uptr)) : pointer(); } 252 ///@endcond 253 }; 254 255 ///@cond 256 257 // Remove cv qualification from Ptr parameter to pointer_traits: 258 template <typename Ptr> 259 struct pointer_traits<const Ptr> : pointer_traits<Ptr> {}; 260 template <typename Ptr> 261 struct pointer_traits<volatile Ptr> : pointer_traits<Ptr> { }; 262 template <typename Ptr> 263 struct pointer_traits<const volatile Ptr> : pointer_traits<Ptr> { }; 264 // Remove reference from Ptr parameter to pointer_traits: 265 template <typename Ptr> 266 struct pointer_traits<Ptr&> : pointer_traits<Ptr> { }; 267 268 ///@endcond 269 270 //! Specialization of pointer_traits for raw pointers 271 //! 272 template <typename T> 273 struct pointer_traits<T*> 274 { 275 typedef T element_type; 276 typedef T* pointer; 277 typedef std::ptrdiff_t difference_type; 278 typedef std::size_t size_type; 279 280 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED 281 typedef T & reference; 282 //!typedef for <pre>U *</pre> 283 //! 284 //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre> 285 //!shall be used instead of rebind<U> to obtain a pointer to U. 286 template <class U> using rebind = U*; 287 #else 288 typedef typename boost::intrusive::detail::unvoid_ref<element_type>::type reference; 289 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) 290 template <class U> using rebind = U*; 291 #endif 292 #endif 293 294 template <class U> struct rebind_pointer 295 { typedef U* type; }; 296 297 //! <b>Returns</b>: addressof(r) 298 //! pointer_toboost::intrusive::pointer_traits299 BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r) BOOST_NOEXCEPT 300 { return boost::intrusive::detail::addressof(r); } 301 302 //! <b>Returns</b>: static_cast<pointer>(uptr) 303 //! 304 template<class U> static_cast_fromboost::intrusive::pointer_traits305 BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(U *uptr) BOOST_NOEXCEPT 306 { return static_cast<pointer>(uptr); } 307 308 //! <b>Returns</b>: const_cast<pointer>(uptr) 309 //! 310 template<class U> const_cast_fromboost::intrusive::pointer_traits311 BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(U *uptr) BOOST_NOEXCEPT 312 { return const_cast<pointer>(uptr); } 313 314 //! <b>Returns</b>: dynamic_cast<pointer>(uptr) 315 //! 316 template<class U> dynamic_cast_fromboost::intrusive::pointer_traits317 BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(U *uptr) BOOST_NOEXCEPT 318 { return dynamic_cast<pointer>(uptr); } 319 }; 320 321 } //namespace container { 322 } //namespace boost { 323 324 #include <boost/intrusive/detail/config_end.hpp> 325 326 #endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP) 327