blob: 4a89397c2c0745477070127af5e5f84881f2cb39 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001//////////////////////////////////////////////////////////////////////////////
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-2012. 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#if (defined _MSC_VER) && (_MSC_VER >= 1200)
21# pragma once
22#endif
23
24#include <ndnboost/intrusive/detail/config_begin.hpp>
25#include <ndnboost/intrusive/detail/workaround.hpp>
26#include <ndnboost/intrusive/detail/memory_util.hpp>
27#include <ndnboost/type_traits/integral_constant.hpp>
28#include <cstddef>
29
30namespace ndnboost {
31namespace intrusive {
32
33//! pointer_traits is the implementation of C++11 std::pointer_traits class with some
34//! extensions like castings.
35//!
36//! pointer_traits supplies a uniform interface to certain attributes of pointer-like types.
37template <typename Ptr>
38struct pointer_traits
39{
40 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
41 //!The pointer type
42 //!queried by this pointer_traits instantiation
43 typedef Ptr pointer;
44
45 //!Ptr::element_type if such a type exists; otherwise, T if Ptr is a class
46 //!template instantiation of the form SomePointer<T, Args>, where Args is zero or
47 //!more type arguments ; otherwise , the specialization is ill-formed.
48 typedef unspecified_type element_type;
49
50 //!Ptr::difference_type if such a type exists; otherwise,
51 //!std::ptrdiff_t.
52 typedef unspecified_type difference_type;
53
54 //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is
55 //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or
56 //!more type arguments ; otherwise, the instantiation of rebind is ill-formed.
57 //!
58 //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre>
59 //!shall be used instead of rebind<U> to obtain a pointer to U.
60 template <class U> using rebind = unspecified;
61
62 //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is
63 //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or
64 //!more type arguments ; otherwise, the instantiation of rebind is ill-formed.
65 //!
66 typedef element_type &reference;
67 #else
68 typedef Ptr pointer;
69 //
70 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT
71 ( ndnboost::intrusive::detail::, Ptr, element_type
72 , ndnboost::intrusive::detail::first_param<Ptr>) element_type;
73 //
74 typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
75 (ndnboost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type;
76 //
77 typedef typename ndnboost::intrusive::detail::unvoid<element_type>::type& reference;
78 //
79 template <class U> struct rebind_pointer
80 {
81 typedef typename ndnboost::intrusive::detail::type_rebinder<Ptr, U>::type type;
82 };
83
84 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
85 template <class U> using rebind = typename ndnboost::intrusive::detail::type_rebinder<Ptr, U>::type;
86 #endif
87 #endif //#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
88
89 //! <b>Remark</b>: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise,
90 //! it is element_type &.
91 //!
92 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(r).
93 //! Non-standard extension: If such function does not exist, returns pointer(addressof(r));
94 static pointer pointer_to(reference r)
95 {
96 //Non-standard extension, it does not require Ptr::pointer_to. If not present
97 //tries to converts &r to pointer.
98 const bool value = ndnboost::intrusive::detail::
99 has_member_function_callable_with_pointer_to
100 <Ptr, typename ndnboost::intrusive::detail::unvoid<element_type &>::type>::value;
101 ::ndnboost::integral_constant<bool, value> flag;
102 return pointer_traits::priv_pointer_to(flag, r);
103 }
104
105 //! <b>Remark</b>: Non-standard extension.
106 //!
107 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::static_cast_from(r).
108 //! If such function does not exist, returns pointer_to(static_cast<element_type&>(*uptr))
109 template<class UPtr>
110 static pointer static_cast_from(const UPtr &uptr)
111 {
112 const bool value = ndnboost::intrusive::detail::
113 has_member_function_callable_with_static_cast_from
114 <Ptr, const UPtr>::value;
115 ::ndnboost::integral_constant<bool, value> flag;
116 return pointer_traits::priv_static_cast_from(flag, uptr);
117 }
118
119 //! <b>Remark</b>: Non-standard extension.
120 //!
121 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::const_cast_from(r).
122 //! If such function does not exist, returns pointer_to(const_cast<element_type&>(*uptr))
123 template<class UPtr>
124 static pointer const_cast_from(const UPtr &uptr)
125 {
126 const bool value = ndnboost::intrusive::detail::
127 has_member_function_callable_with_const_cast_from
128 <Ptr, const UPtr>::value;
129 ::ndnboost::integral_constant<bool, value> flag;
130 return pointer_traits::priv_const_cast_from(flag, uptr);
131 }
132
133 //! <b>Remark</b>: Non-standard extension.
134 //!
135 //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::dynamic_cast_from(r).
136 //! If such function does not exist, returns pointer_to(*dynamic_cast<element_type*>(&*uptr))
137 template<class UPtr>
138 static pointer dynamic_cast_from(const UPtr &uptr)
139 {
140 const bool value = ndnboost::intrusive::detail::
141 has_member_function_callable_with_dynamic_cast_from
142 <Ptr, const UPtr>::value;
143 ::ndnboost::integral_constant<bool, value> flag;
144 return pointer_traits::priv_dynamic_cast_from(flag, uptr);
145 }
146
147 ///@cond
148 private:
149 //priv_to_raw_pointer
150 template <class T>
151 static T* to_raw_pointer(T* p)
152 { return p; }
153
154 template <class Pointer>
155 static typename pointer_traits<Pointer>::element_type*
156 to_raw_pointer(const Pointer &p)
157 { return pointer_traits::to_raw_pointer(p.operator->()); }
158
159 //priv_pointer_to
160 static pointer priv_pointer_to(ndnboost::true_type, typename ndnboost::intrusive::detail::unvoid<element_type>::type& r)
161 { return Ptr::pointer_to(r); }
162
163 static pointer priv_pointer_to(ndnboost::false_type, typename ndnboost::intrusive::detail::unvoid<element_type>::type& r)
164 { return pointer(ndnboost::intrusive::detail::addressof(r)); }
165
166 //priv_static_cast_from
167 template<class UPtr>
168 static pointer priv_static_cast_from(ndnboost::true_type, const UPtr &uptr)
169 { return Ptr::static_cast_from(uptr); }
170
171 template<class UPtr>
172 static pointer priv_static_cast_from(ndnboost::false_type, const UPtr &uptr)
173 { return pointer_to(*static_cast<element_type*>(to_raw_pointer(uptr))); }
174
175 //priv_const_cast_from
176 template<class UPtr>
177 static pointer priv_const_cast_from(ndnboost::true_type, const UPtr &uptr)
178 { return Ptr::const_cast_from(uptr); }
179
180 template<class UPtr>
181 static pointer priv_const_cast_from(ndnboost::false_type, const UPtr &uptr)
182 { return pointer_to(const_cast<element_type&>(*uptr)); }
183
184 //priv_dynamic_cast_from
185 template<class UPtr>
186 static pointer priv_dynamic_cast_from(ndnboost::true_type, const UPtr &uptr)
187 { return Ptr::dynamic_cast_from(uptr); }
188
189 template<class UPtr>
190 static pointer priv_dynamic_cast_from(ndnboost::false_type, const UPtr &uptr)
191 { return pointer_to(*dynamic_cast<element_type*>(&*uptr)); }
192 ///@endcond
193};
194
195///@cond
196
197// Remove cv qualification from Ptr parameter to pointer_traits:
198template <typename Ptr>
199struct pointer_traits<const Ptr> : pointer_traits<Ptr> {};
200template <typename Ptr>
201struct pointer_traits<volatile Ptr> : pointer_traits<Ptr> { };
202template <typename Ptr>
203struct pointer_traits<const volatile Ptr> : pointer_traits<Ptr> { };
204// Remove reference from Ptr parameter to pointer_traits:
205template <typename Ptr>
206struct pointer_traits<Ptr&> : pointer_traits<Ptr> { };
207
208///@endcond
209
210//! Specialization of pointer_traits for raw pointers
211//!
212template <typename T>
213struct pointer_traits<T*>
214{
215 typedef T element_type;
216 typedef T* pointer;
217 typedef std::ptrdiff_t difference_type;
218
219 #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
220 typedef T & reference;
221 //!typedef for <pre>U *</pre>
222 //!
223 //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre>
224 //!shall be used instead of rebind<U> to obtain a pointer to U.
225 template <class U> using rebind = U*;
226 #else
227 typedef typename ndnboost::intrusive::detail::unvoid<element_type>::type& reference;
228 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
229 template <class U> using rebind = U*;
230 #endif
231 #endif
232
233 template <class U> struct rebind_pointer
234 { typedef U* type; };
235
236 //! <b>Returns</b>: addressof(r)
237 //!
238 static pointer pointer_to(reference r)
239 { return ndnboost::intrusive::detail::addressof(r); }
240
241 //! <b>Returns</b>: static_cast<pointer>(uptr)
242 //!
243 template<class U>
244 static pointer static_cast_from(U *uptr)
245 { return static_cast<pointer>(uptr); }
246
247 //! <b>Returns</b>: const_cast<pointer>(uptr)
248 //!
249 template<class U>
250 static pointer const_cast_from(U *uptr)
251 { return const_cast<pointer>(uptr); }
252
253 //! <b>Returns</b>: dynamic_cast<pointer>(uptr)
254 //!
255 template<class U>
256 static pointer dynamic_cast_from(U *uptr)
257 { return dynamic_cast<pointer>(uptr); }
258};
259
260} //namespace container {
261} //namespace ndnboost {
262
263#include <ndnboost/intrusive/detail/config_end.hpp>
264
265#endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP)