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