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