]>
Commit | Line | Data |
---|---|---|
517f369a | 1 | // Custom pointer adapter and sample storage policies |
2 | ||
fbd26352 | 3 | // Copyright (C) 2008-2019 Free Software Foundation, Inc. |
517f369a | 4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
6bc9506f | 8 | // Free Software Foundation; either version 3, or (at your option) |
517f369a | 9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
6bc9506f | 16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
517f369a | 19 | |
6bc9506f | 20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
517f369a | 24 | |
25 | /** | |
5846aeac | 26 | * @file ext/pointer.h |
27 | * This file is a GNU extension to the Standard C++ Library. | |
28 | * | |
29 | * @author Bob Walters | |
517f369a | 30 | * |
31 | * Provides reusable _Pointer_adapter for assisting in the development of | |
3ff57f2d | 32 | * custom pointer types that can be used with the standard containers via |
517f369a | 33 | * the allocator::pointer and allocator::const_pointer typedefs. |
34 | */ | |
35 | ||
3ff57f2d | 36 | #ifndef _POINTER_H |
37 | #define _POINTER_H 1 | |
517f369a | 38 | |
91512d88 | 39 | #pragma GCC system_header |
40 | ||
3ff57f2d | 41 | #include <iosfwd> |
42 | #include <bits/stl_iterator_base_types.h> | |
517f369a | 43 | #include <ext/cast.h> |
43f03e4b | 44 | #include <ext/type_traits.h> |
0c8766b1 | 45 | #if __cplusplus >= 201103L |
d2c24105 | 46 | # include <bits/move.h> |
ca7dce6a | 47 | # include <bits/ptr_traits.h> |
48 | #endif | |
517f369a | 49 | |
2948dd21 | 50 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) |
51 | { | |
52 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
517f369a | 53 | |
54 | /** | |
55 | * @brief A storage policy for use with _Pointer_adapter<> which yields a | |
56 | * standard pointer. | |
57 | * | |
58 | * A _Storage_policy is required to provide 4 things: | |
59 | * 1) A get() API for returning the stored pointer value. | |
60 | * 2) An set() API for storing a pointer value. | |
61 | * 3) An element_type typedef to define the type this points to. | |
62 | * 4) An operator<() to support pointer comparison. | |
63 | * 5) An operator==() to support pointer comparison. | |
64 | */ | |
3ff57f2d | 65 | template<typename _Tp> |
517f369a | 66 | class _Std_pointer_impl |
67 | { | |
68 | public: | |
69 | // the type this pointer points to. | |
3ff57f2d | 70 | typedef _Tp element_type; |
517f369a | 71 | |
72 | // A method to fetch the pointer value as a standard T* value; | |
3ff57f2d | 73 | inline _Tp* |
517f369a | 74 | get() const |
75 | { return _M_value; } | |
76 | ||
77 | // A method to set the pointer value, from a standard T* value; | |
78 | inline void | |
79 | set(element_type* __arg) | |
80 | { _M_value = __arg; } | |
81 | ||
82 | // Comparison of pointers | |
83 | inline bool | |
84 | operator<(const _Std_pointer_impl& __rarg) const | |
85 | { return (_M_value < __rarg._M_value); } | |
86 | ||
87 | inline bool | |
88 | operator==(const _Std_pointer_impl& __rarg) const | |
89 | { return (_M_value == __rarg._M_value); } | |
90 | ||
91 | private: | |
92 | element_type* _M_value; | |
93 | }; | |
94 | ||
517f369a | 95 | /** |
96 | * @brief A storage policy for use with _Pointer_adapter<> which stores | |
97 | * the pointer's address as an offset value which is relative to | |
98 | * its own address. | |
99 | * | |
91512d88 | 100 | * This is intended for pointers within shared memory regions which |
101 | * might be mapped at different addresses by different processes. | |
102 | * For null pointers, a value of 1 is used. (0 is legitimate | |
103 | * sometimes for nodes in circularly linked lists) This value was | |
104 | * chosen as the least likely to generate an incorrect null, As | |
105 | * there is no reason why any normal pointer would point 1 byte into | |
517f369a | 106 | * its own pointer address. |
107 | */ | |
3ff57f2d | 108 | template<typename _Tp> |
517f369a | 109 | class _Relative_pointer_impl |
110 | { | |
111 | public: | |
3ff57f2d | 112 | typedef _Tp element_type; |
517f369a | 113 | |
3ff57f2d | 114 | _Tp* |
517f369a | 115 | get() const |
116 | { | |
117 | if (_M_diff == 1) | |
3ff57f2d | 118 | return 0; |
517f369a | 119 | else |
43f03e4b | 120 | return reinterpret_cast<_Tp*>(reinterpret_cast<_UIntPtrType>(this) |
121 | + _M_diff); | |
517f369a | 122 | } |
123 | ||
124 | void | |
3ff57f2d | 125 | set(_Tp* __arg) |
517f369a | 126 | { |
3ff57f2d | 127 | if (!__arg) |
517f369a | 128 | _M_diff = 1; |
129 | else | |
43f03e4b | 130 | _M_diff = reinterpret_cast<_UIntPtrType>(__arg) |
131 | - reinterpret_cast<_UIntPtrType>(this); | |
517f369a | 132 | } |
133 | ||
134 | // Comparison of pointers | |
135 | inline bool | |
136 | operator<(const _Relative_pointer_impl& __rarg) const | |
43f03e4b | 137 | { return (reinterpret_cast<_UIntPtrType>(this->get()) |
138 | < reinterpret_cast<_UIntPtrType>(__rarg.get())); } | |
517f369a | 139 | |
140 | inline bool | |
141 | operator==(const _Relative_pointer_impl& __rarg) const | |
43f03e4b | 142 | { return (reinterpret_cast<_UIntPtrType>(this->get()) |
143 | == reinterpret_cast<_UIntPtrType>(__rarg.get())); } | |
517f369a | 144 | |
145 | private: | |
91512d88 | 146 | #ifdef _GLIBCXX_USE_LONG_LONG |
43f03e4b | 147 | typedef __gnu_cxx::__conditional_type< |
148 | (sizeof(unsigned long) >= sizeof(void*)), | |
149 | unsigned long, unsigned long long>::__type _UIntPtrType; | |
91512d88 | 150 | #else |
151 | typedef unsigned long _UIntPtrType; | |
152 | #endif | |
43f03e4b | 153 | _UIntPtrType _M_diff; |
517f369a | 154 | }; |
155 | ||
156 | /** | |
157 | * Relative_pointer_impl needs a specialization for const T because of | |
158 | * the casting done during pointer arithmetic. | |
159 | */ | |
3ff57f2d | 160 | template<typename _Tp> |
161 | class _Relative_pointer_impl<const _Tp> | |
517f369a | 162 | { |
163 | public: | |
3ff57f2d | 164 | typedef const _Tp element_type; |
517f369a | 165 | |
3ff57f2d | 166 | const _Tp* |
517f369a | 167 | get() const |
168 | { | |
169 | if (_M_diff == 1) | |
3ff57f2d | 170 | return 0; |
517f369a | 171 | else |
43f03e4b | 172 | return reinterpret_cast<const _Tp*> |
173 | (reinterpret_cast<_UIntPtrType>(this) + _M_diff); | |
517f369a | 174 | } |
175 | ||
176 | void | |
3ff57f2d | 177 | set(const _Tp* __arg) |
517f369a | 178 | { |
3ff57f2d | 179 | if (!__arg) |
517f369a | 180 | _M_diff = 1; |
181 | else | |
43f03e4b | 182 | _M_diff = reinterpret_cast<_UIntPtrType>(__arg) |
183 | - reinterpret_cast<_UIntPtrType>(this); | |
517f369a | 184 | } |
185 | ||
186 | // Comparison of pointers | |
187 | inline bool | |
188 | operator<(const _Relative_pointer_impl& __rarg) const | |
43f03e4b | 189 | { return (reinterpret_cast<_UIntPtrType>(this->get()) |
190 | < reinterpret_cast<_UIntPtrType>(__rarg.get())); } | |
517f369a | 191 | |
192 | inline bool | |
193 | operator==(const _Relative_pointer_impl& __rarg) const | |
43f03e4b | 194 | { return (reinterpret_cast<_UIntPtrType>(this->get()) |
195 | == reinterpret_cast<_UIntPtrType>(__rarg.get())); } | |
517f369a | 196 | |
197 | private: | |
91512d88 | 198 | #ifdef _GLIBCXX_USE_LONG_LONG |
199 | typedef __gnu_cxx::__conditional_type< | |
200 | (sizeof(unsigned long) >= sizeof(void*)), | |
43f03e4b | 201 | unsigned long, unsigned long long>::__type _UIntPtrType; |
91512d88 | 202 | #else |
203 | typedef unsigned long _UIntPtrType; | |
204 | #endif | |
205 | _UIntPtrType _M_diff; | |
517f369a | 206 | }; |
207 | ||
517f369a | 208 | /** |
209 | * The specialization on this type helps resolve the problem of | |
91512d88 | 210 | * reference to void, and eliminates the need to specialize |
211 | * _Pointer_adapter for cases of void*, const void*, and so on. | |
517f369a | 212 | */ |
213 | struct _Invalid_type { }; | |
214 | ||
215 | template<typename _Tp> | |
216 | struct _Reference_type | |
3ff57f2d | 217 | { typedef _Tp& reference; }; |
517f369a | 218 | |
219 | template<> | |
220 | struct _Reference_type<void> | |
3ff57f2d | 221 | { typedef _Invalid_type& reference; }; |
517f369a | 222 | |
223 | template<> | |
224 | struct _Reference_type<const void> | |
3ff57f2d | 225 | { typedef const _Invalid_type& reference; }; |
517f369a | 226 | |
227 | template<> | |
228 | struct _Reference_type<volatile void> | |
3ff57f2d | 229 | { typedef volatile _Invalid_type& reference; }; |
517f369a | 230 | |
231 | template<> | |
232 | struct _Reference_type<volatile const void> | |
3ff57f2d | 233 | { typedef const volatile _Invalid_type& reference; }; |
517f369a | 234 | |
235 | /** | |
4ba0945f | 236 | * This structure accommodates the way in which |
91512d88 | 237 | * std::iterator_traits<> is normally specialized for const T*, so |
238 | * that value_type is still T. | |
517f369a | 239 | */ |
240 | template<typename _Tp> | |
241 | struct _Unqualified_type | |
3ff57f2d | 242 | { typedef _Tp type; }; |
517f369a | 243 | |
244 | template<typename _Tp> | |
245 | struct _Unqualified_type<const _Tp> | |
3ff57f2d | 246 | { typedef _Tp type; }; |
517f369a | 247 | |
517f369a | 248 | /** |
91512d88 | 249 | * The following provides an 'alternative pointer' that works with |
250 | * the containers when specified as the pointer typedef of the | |
251 | * allocator. | |
3ff57f2d | 252 | * |
91512d88 | 253 | * The pointer type used with the containers doesn't have to be this |
254 | * class, but it must support the implicit conversions, pointer | |
255 | * arithmetic, comparison operators, etc. that are supported by this | |
256 | * class, and avoid raising compile-time ambiguities. Because | |
257 | * creating a working pointer can be challenging, this pointer | |
258 | * template was designed to wrapper an easier storage policy type, | |
259 | * so that it becomes reusable for creating other pointer types. | |
517f369a | 260 | * |
91512d88 | 261 | * A key point of this class is also that it allows container |
4ba0945f | 262 | * writers to 'assume' Allocator::pointer is a typedef for a normal |
91512d88 | 263 | * pointer. This class supports most of the conventions of a true |
264 | * pointer, and can, for instance handle implicit conversion to | |
265 | * const and base class pointer types. The only impositions on | |
266 | * container writers to support extended pointers are: 1) use the | |
267 | * Allocator::pointer typedef appropriately for pointer types. 2) | |
268 | * if you need pointer casting, use the __pointer_cast<> functions | |
269 | * from ext/cast.h. This allows pointer cast operations to be | |
4ba0945f | 270 | * overloaded as necessary by custom pointers. |
517f369a | 271 | * |
91512d88 | 272 | * Note: The const qualifier works with this pointer adapter as |
273 | * follows: | |
517f369a | 274 | * |
275 | * _Tp* == _Pointer_adapter<_Std_pointer_impl<_Tp> >; | |
276 | * const _Tp* == _Pointer_adapter<_Std_pointer_impl<const _Tp> >; | |
277 | * _Tp* const == const _Pointer_adapter<_Std_pointer_impl<_Tp> >; | |
278 | * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >; | |
279 | */ | |
3ff57f2d | 280 | template<typename _Storage_policy> |
517f369a | 281 | class _Pointer_adapter : public _Storage_policy |
282 | { | |
283 | public: | |
284 | typedef typename _Storage_policy::element_type element_type; | |
3ff57f2d | 285 | |
517f369a | 286 | // These are needed for iterator_traits |
287 | typedef std::random_access_iterator_tag iterator_category; | |
288 | typedef typename _Unqualified_type<element_type>::type value_type; | |
3ff57f2d | 289 | typedef std::ptrdiff_t difference_type; |
517f369a | 290 | typedef _Pointer_adapter pointer; |
291 | typedef typename _Reference_type<element_type>::reference reference; | |
3ff57f2d | 292 | |
517f369a | 293 | // Reminder: 'const' methods mean that the method is valid when the |
294 | // pointer is immutable, and has nothing to do with whether the | |
295 | // 'pointee' is const. | |
296 | ||
297 | // Default Constructor (Convert from element_type*) | |
3ff57f2d | 298 | _Pointer_adapter(element_type* __arg = 0) |
517f369a | 299 | { _Storage_policy::set(__arg); } |
3ff57f2d | 300 | |
517f369a | 301 | // Copy constructor from _Pointer_adapter of same type. |
302 | _Pointer_adapter(const _Pointer_adapter& __arg) | |
303 | { _Storage_policy::set(__arg.get()); } | |
3ff57f2d | 304 | |
517f369a | 305 | // Convert from _Up* if conversion to element_type* is valid. |
306 | template<typename _Up> | |
3ff57f2d | 307 | _Pointer_adapter(_Up* __arg) |
308 | { _Storage_policy::set(__arg); } | |
309 | ||
517f369a | 310 | // Conversion from another _Pointer_adapter if _Up if static cast is |
311 | // valid. | |
312 | template<typename _Up> | |
313 | _Pointer_adapter(const _Pointer_adapter<_Up>& __arg) | |
3ff57f2d | 314 | { _Storage_policy::set(__arg.get()); } |
315 | ||
517f369a | 316 | // Destructor |
317 | ~_Pointer_adapter() { } | |
318 | ||
319 | // Assignment operator | |
320 | _Pointer_adapter& | |
321 | operator=(const _Pointer_adapter& __arg) | |
322 | { | |
323 | _Storage_policy::set(__arg.get()); | |
324 | return *this; | |
325 | } | |
3ff57f2d | 326 | |
517f369a | 327 | template<typename _Up> |
328 | _Pointer_adapter& | |
329 | operator=(const _Pointer_adapter<_Up>& __arg) | |
330 | { | |
331 | _Storage_policy::set(__arg.get()); | |
332 | return *this; | |
333 | } | |
334 | ||
335 | template<typename _Up> | |
336 | _Pointer_adapter& | |
337 | operator=(_Up* __arg) | |
338 | { | |
339 | _Storage_policy::set(__arg); | |
340 | return *this; | |
341 | } | |
342 | ||
343 | // Operator*, returns element_type& | |
344 | inline reference | |
345 | operator*() const | |
346 | { return *(_Storage_policy::get()); } | |
3ff57f2d | 347 | |
517f369a | 348 | // Operator->, returns element_type* |
349 | inline element_type* | |
350 | operator->() const | |
351 | { return _Storage_policy::get(); } | |
3ff57f2d | 352 | |
517f369a | 353 | // Operator[], returns a element_type& to the item at that loc. |
3ff57f2d | 354 | inline reference |
355 | operator[](std::ptrdiff_t __index) const | |
517f369a | 356 | { return _Storage_policy::get()[__index]; } |
3ff57f2d | 357 | |
517f369a | 358 | // To allow implicit conversion to "bool", for "if (ptr)..." |
22bbe014 | 359 | #if __cplusplus >= 201103L |
360 | explicit operator bool() const { return _Storage_policy::get() != 0; } | |
361 | #else | |
517f369a | 362 | private: |
363 | typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const; | |
364 | ||
365 | public: | |
366 | operator __unspecified_bool_type() const | |
367 | { | |
368 | return _Storage_policy::get() == 0 ? 0 : | |
369 | &_Pointer_adapter::operator->; | |
370 | } | |
371 | ||
372 | // ! operator (for: if (!ptr)...) | |
3ff57f2d | 373 | inline bool |
517f369a | 374 | operator!() const |
3ff57f2d | 375 | { return (_Storage_policy::get() == 0); } |
22bbe014 | 376 | #endif |
517f369a | 377 | |
378 | // Pointer differences | |
379 | inline friend std::ptrdiff_t | |
380 | operator-(const _Pointer_adapter& __lhs, element_type* __rhs) | |
381 | { return (__lhs.get() - __rhs); } | |
382 | ||
383 | inline friend std::ptrdiff_t | |
384 | operator-(element_type* __lhs, const _Pointer_adapter& __rhs) | |
385 | { return (__lhs - __rhs.get()); } | |
386 | ||
3ff57f2d | 387 | template<typename _Up> |
517f369a | 388 | inline friend std::ptrdiff_t |
389 | operator-(const _Pointer_adapter& __lhs, _Up* __rhs) | |
390 | { return (__lhs.get() - __rhs); } | |
391 | ||
3ff57f2d | 392 | template<typename _Up> |
517f369a | 393 | inline friend std::ptrdiff_t |
394 | operator-(_Up* __lhs, const _Pointer_adapter& __rhs) | |
395 | { return (__lhs - __rhs.get()); } | |
396 | ||
397 | template<typename _Up> | |
398 | inline std::ptrdiff_t | |
399 | operator-(const _Pointer_adapter<_Up>& __rhs) const | |
400 | { return (_Storage_policy::get() - __rhs.get()); } | |
401 | ||
402 | // Pointer math | |
403 | // Note: There is a reason for all this overloading based on different | |
404 | // integer types. In some libstdc++-v3 test cases, a templated | |
405 | // operator+ is declared which can match any types. This operator | |
406 | // tends to "steal" the recognition of _Pointer_adapter's own operator+ | |
407 | // unless the integer type matches perfectly. | |
408 | ||
409 | #define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \ | |
410 | inline friend _Pointer_adapter \ | |
411 | operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \ | |
412 | { return _Pointer_adapter(__lhs.get() + __offset); } \ | |
413 | \ | |
414 | inline friend _Pointer_adapter \ | |
415 | operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \ | |
416 | { return _Pointer_adapter(__rhs.get() + __offset); } \ | |
417 | \ | |
418 | inline friend _Pointer_adapter \ | |
419 | operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \ | |
420 | { return _Pointer_adapter(__lhs.get() - __offset); } \ | |
421 | \ | |
422 | inline _Pointer_adapter& \ | |
423 | operator+=(INT_TYPE __offset) \ | |
424 | { \ | |
425 | _Storage_policy::set(_Storage_policy::get() + __offset); \ | |
426 | return *this; \ | |
427 | } \ | |
428 | \ | |
429 | inline _Pointer_adapter& \ | |
430 | operator-=(INT_TYPE __offset) \ | |
431 | { \ | |
432 | _Storage_policy::set(_Storage_policy::get() - __offset); \ | |
433 | return *this; \ | |
434 | } \ | |
435 | // END of _CXX_POINTER_ARITH_OPERATOR_SET macro | |
436 | ||
4ba0945f | 437 | // Expand into the various pointer arithmetic operators needed. |
517f369a | 438 | _CXX_POINTER_ARITH_OPERATOR_SET(short); |
439 | _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short); | |
440 | _CXX_POINTER_ARITH_OPERATOR_SET(int); | |
441 | _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int); | |
442 | _CXX_POINTER_ARITH_OPERATOR_SET(long); | |
443 | _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long); | |
549d33da | 444 | #ifdef _GLIBCXX_USE_LONG_LONG |
445 | _CXX_POINTER_ARITH_OPERATOR_SET(long long); | |
446 | _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long); | |
447 | #endif | |
517f369a | 448 | |
449 | // Mathematical Manipulators | |
450 | inline _Pointer_adapter& | |
451 | operator++() | |
452 | { | |
453 | _Storage_policy::set(_Storage_policy::get() + 1); | |
454 | return *this; | |
455 | } | |
456 | ||
457 | inline _Pointer_adapter | |
857a5f5d | 458 | operator++(int) |
517f369a | 459 | { |
6e9c114d | 460 | _Pointer_adapter __tmp(*this); |
517f369a | 461 | _Storage_policy::set(_Storage_policy::get() + 1); |
6e9c114d | 462 | return __tmp; |
517f369a | 463 | } |
464 | ||
465 | inline _Pointer_adapter& | |
466 | operator--() | |
467 | { | |
468 | _Storage_policy::set(_Storage_policy::get() - 1); | |
469 | return *this; | |
470 | } | |
471 | ||
472 | inline _Pointer_adapter | |
3ff57f2d | 473 | operator--(int) |
517f369a | 474 | { |
6e9c114d | 475 | _Pointer_adapter __tmp(*this); |
517f369a | 476 | _Storage_policy::set(_Storage_policy::get() - 1); |
6e9c114d | 477 | return __tmp; |
517f369a | 478 | } |
479 | ||
480 | }; // class _Pointer_adapter | |
481 | ||
482 | ||
91512d88 | 483 | #define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \ |
517f369a | 484 | template<typename _Tp1, typename _Tp2> \ |
485 | inline bool \ | |
91512d88 | 486 | operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \ |
487 | { return __lhs.get() OPERATOR __rhs; } \ | |
517f369a | 488 | \ |
489 | template<typename _Tp1, typename _Tp2> \ | |
490 | inline bool \ | |
91512d88 | 491 | operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \ |
492 | { return __lhs OPERATOR __rhs.get(); } \ | |
517f369a | 493 | \ |
494 | template<typename _Tp1, typename _Tp2> \ | |
495 | inline bool \ | |
91512d88 | 496 | operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \ |
517f369a | 497 | const _Pointer_adapter<_Tp2>& __rhs) \ |
91512d88 | 498 | { return __lhs.get() OPERATOR __rhs.get(); } \ |
517f369a | 499 | \ |
500 | // End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro | |
501 | ||
502 | // Expand into the various comparison operators needed. | |
91512d88 | 503 | _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==) |
504 | _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=) | |
505 | _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<) | |
506 | _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=) | |
507 | _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>) | |
508 | _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=) | |
517f369a | 509 | |
517f369a | 510 | // These are here for expressions like "ptr == 0", "ptr != 0" |
511 | template<typename _Tp> | |
512 | inline bool | |
513 | operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs) | |
514 | { return __lhs.get() == reinterpret_cast<void*>(__rhs); } | |
515 | ||
516 | template<typename _Tp> | |
517 | inline bool | |
518 | operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs) | |
519 | { return __rhs.get() == reinterpret_cast<void*>(__lhs); } | |
520 | ||
521 | template<typename _Tp> | |
522 | inline bool | |
523 | operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs) | |
524 | { return __lhs.get() != reinterpret_cast<void*>(__rhs); } | |
525 | ||
526 | template<typename _Tp> | |
527 | inline bool | |
528 | operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs) | |
529 | { return __rhs.get() != reinterpret_cast<void*>(__lhs); } | |
530 | ||
531 | /** | |
4ba0945f | 532 | * Comparison operators for _Pointer_adapter defer to the base class' |
517f369a | 533 | * comparison operators, when possible. |
534 | */ | |
535 | template<typename _Tp> | |
536 | inline bool | |
537 | operator==(const _Pointer_adapter<_Tp>& __lhs, | |
538 | const _Pointer_adapter<_Tp>& __rhs) | |
539 | { return __lhs._Tp::operator==(__rhs); } | |
3ff57f2d | 540 | |
517f369a | 541 | template<typename _Tp> |
542 | inline bool | |
543 | operator<=(const _Pointer_adapter<_Tp>& __lhs, | |
544 | const _Pointer_adapter<_Tp>& __rhs) | |
545 | { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); } | |
3ff57f2d | 546 | |
517f369a | 547 | template<typename _Tp> |
548 | inline bool | |
549 | operator!=(const _Pointer_adapter<_Tp>& __lhs, | |
550 | const _Pointer_adapter<_Tp>& __rhs) | |
551 | { return !(__lhs._Tp::operator==(__rhs)); } | |
3ff57f2d | 552 | |
517f369a | 553 | template<typename _Tp> |
554 | inline bool | |
555 | operator>(const _Pointer_adapter<_Tp>& __lhs, | |
556 | const _Pointer_adapter<_Tp>& __rhs) | |
557 | { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); } | |
3ff57f2d | 558 | |
517f369a | 559 | template<typename _Tp> |
560 | inline bool | |
561 | operator>=(const _Pointer_adapter<_Tp>& __lhs, | |
562 | const _Pointer_adapter<_Tp>& __rhs) | |
563 | { return !(__lhs._Tp::operator<(__rhs)); } | |
3ff57f2d | 564 | |
565 | template<typename _CharT, typename _Traits, typename _StoreT> | |
566 | inline std::basic_ostream<_CharT, _Traits>& | |
567 | operator<<(std::basic_ostream<_CharT, _Traits>& __os, | |
517f369a | 568 | const _Pointer_adapter<_StoreT>& __p) |
3ff57f2d | 569 | { return (__os << __p.get()); } |
517f369a | 570 | |
2948dd21 | 571 | _GLIBCXX_END_NAMESPACE_VERSION |
572 | } // namespace | |
517f369a | 573 | |
0c8766b1 | 574 | #if __cplusplus >= 201103L |
ca7dce6a | 575 | namespace std _GLIBCXX_VISIBILITY(default) |
576 | { | |
577 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
578 | ||
579 | template<typename _Storage_policy> | |
580 | struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>> | |
581 | { | |
582 | /// The pointer type | |
583 | typedef __gnu_cxx::_Pointer_adapter<_Storage_policy> pointer; | |
584 | /// The type pointed to | |
585 | typedef typename pointer::element_type element_type; | |
586 | /// Type used to represent the difference between two pointers | |
587 | typedef typename pointer::difference_type difference_type; | |
588 | ||
ca7dce6a | 589 | template<typename _Up> |
e8564ee9 | 590 | using rebind = typename __gnu_cxx::_Pointer_adapter< |
616429ae | 591 | typename pointer_traits<_Storage_policy>::template rebind<_Up>>; |
4ba0945f | 592 | |
593 | static pointer pointer_to(typename pointer::reference __r) noexcept | |
594 | { return pointer(std::addressof(__r)); } | |
ca7dce6a | 595 | }; |
596 | ||
597 | _GLIBCXX_END_NAMESPACE_VERSION | |
598 | } // namespace | |
599 | #endif | |
600 | ||
3ff57f2d | 601 | #endif // _POINTER_H |