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/intrusive/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 pdalboost {
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          ( pdalboost::intrusive::detail::, Ptr, element_type
100          , pdalboost::intrusive::detail::first_param<Ptr>)                        element_type;
101       //
102       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
103          (pdalboost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t)   difference_type;
104 
105       typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
106          (pdalboost::intrusive::detail::, Ptr, reference, typename pdalboost::intrusive::detail::unvoid_ref<element_type>::type)   reference;
107       //
108       template <class U> struct rebind_pointer
109       {
110          typedef typename pdalboost::intrusive::pointer_rebind<Ptr, U>::type  type;
111       };
112 
113       #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
114          template <class U> using rebind = typename pdalboost::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_topdalboost::intrusive::pointer_traits126    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 = pdalboost::intrusive::detail::
131          has_member_function_callable_with_pointer_to
132             <Ptr, Ptr (*)(reference)>::value;
133       pdalboost::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_frompdalboost::intrusive::pointer_traits146    static pointer static_cast_from(const UPtr &uptr)
147    {
148       typedef const UPtr &RefArg;
149       const bool value = pdalboost::intrusive::detail::
150          has_member_function_callable_with_static_cast_from
151             <pointer, pointer(*)(RefArg)>::value
152          || pdalboost::intrusive::detail::
153                has_member_function_callable_with_static_cast_from
154                   <pointer, pointer(*)(UPtr)>::value;
155       return pointer_traits::priv_static_cast_from(pdalboost::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_frompdalboost::intrusive::pointer_traits167    static pointer const_cast_from(const UPtr &uptr)
168    {
169       typedef const UPtr &RefArg;
170       const bool value = pdalboost::intrusive::detail::
171          has_member_function_callable_with_const_cast_from
172             <pointer, pointer(*)(RefArg)>::value
173          || pdalboost::intrusive::detail::
174                has_member_function_callable_with_const_cast_from
175                   <pointer, pointer(*)(UPtr)>::value;
176       return pointer_traits::priv_const_cast_from(pdalboost::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_frompdalboost::intrusive::pointer_traits188    static pointer dynamic_cast_from(const UPtr &uptr)
189    {
190       typedef const UPtr &RefArg;
191       const bool value = pdalboost::intrusive::detail::
192          has_member_function_callable_with_dynamic_cast_from
193             <pointer, pointer(*)(RefArg)>::value
194          || pdalboost::intrusive::detail::
195                has_member_function_callable_with_dynamic_cast_from
196                   <pointer, pointer(*)(UPtr)>::value;
197       return pointer_traits::priv_dynamic_cast_from(pdalboost::intrusive::detail::bool_<value>(), uptr);
198    }
199 
200    ///@cond
201    private:
202    //priv_to_raw_pointer
203    template <class T>
to_raw_pointerpdalboost::intrusive::pointer_traits204    static T* to_raw_pointer(T* p)
205    {  return p; }
206 
207    template <class Pointer>
208    static typename pointer_traits<Pointer>::element_type*
to_raw_pointerpdalboost::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_topdalboost::intrusive::pointer_traits213    static pointer priv_pointer_to(pdalboost::intrusive::detail::true_, reference r)
214    { return Ptr::pointer_to(r); }
215 
priv_pointer_topdalboost::intrusive::pointer_traits216    static pointer priv_pointer_to(pdalboost::intrusive::detail::false_, reference r)
217    { return pointer(pdalboost::intrusive::detail::addressof(r)); }
218 
219    //priv_static_cast_from
220    template<class UPtr>
priv_static_cast_frompdalboost::intrusive::pointer_traits221    static pointer priv_static_cast_from(pdalboost::intrusive::detail::true_, const UPtr &uptr)
222    { return Ptr::static_cast_from(uptr); }
223 
224    template<class UPtr>
priv_static_cast_frompdalboost::intrusive::pointer_traits225    static pointer priv_static_cast_from(pdalboost::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_frompdalboost::intrusive::pointer_traits230    static pointer priv_const_cast_from(pdalboost::intrusive::detail::true_, const UPtr &uptr)
231    { return Ptr::const_cast_from(uptr); }
232 
233    template<class UPtr>
priv_const_cast_frompdalboost::intrusive::pointer_traits234    static pointer priv_const_cast_from(pdalboost::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_frompdalboost::intrusive::pointer_traits239    static pointer priv_dynamic_cast_from(pdalboost::intrusive::detail::true_, const UPtr &uptr)
240    { return Ptr::dynamic_cast_from(uptr); }
241 
242    template<class UPtr>
priv_dynamic_cast_frompdalboost::intrusive::pointer_traits243    static pointer priv_dynamic_cast_from(pdalboost::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 pdalboost::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_topdalboost::intrusive::pointer_traits291    static pointer pointer_to(reference r)
292    { return pdalboost::intrusive::detail::addressof(r); }
293 
294    //! <b>Returns</b>: static_cast<pointer>(uptr)
295    //!
296    template<class U>
static_cast_frompdalboost::intrusive::pointer_traits297    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_frompdalboost::intrusive::pointer_traits303    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_frompdalboost::intrusive::pointer_traits309    static pointer dynamic_cast_from(U *uptr)
310    {  return dynamic_cast<pointer>(uptr);  }
311 };
312 
313 }  //namespace container {
314 }  //namespace pdalboost {
315 
316 #include <boost/intrusive/detail/config_end.hpp>
317 
318 #endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP)
319