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