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