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