xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/ext/pointer.h (revision b1e838363e3c6fc78a55519254d99869742dd33c)
14fee23f9Smrg // Custom pointer adapter and sample storage policies
24fee23f9Smrg 
3*b1e83836Smrg // Copyright (C) 2008-2022 Free Software Foundation, Inc.
44fee23f9Smrg //
54fee23f9Smrg // This file is part of the GNU ISO C++ Library.  This library is free
64fee23f9Smrg // software; you can redistribute it and/or modify it under the
74fee23f9Smrg // terms of the GNU General Public License as published by the
84fee23f9Smrg // Free Software Foundation; either version 3, or (at your option)
94fee23f9Smrg // any later version.
104fee23f9Smrg 
114fee23f9Smrg // This library is distributed in the hope that it will be useful,
124fee23f9Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg // GNU General Public License for more details.
154fee23f9Smrg 
164fee23f9Smrg // Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg // permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg // 3.1, as published by the Free Software Foundation.
194fee23f9Smrg 
204fee23f9Smrg // You should have received a copy of the GNU General Public License and
214fee23f9Smrg // a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg // <http://www.gnu.org/licenses/>.
244fee23f9Smrg 
254fee23f9Smrg /**
264fee23f9Smrg  *  @file ext/pointer.h
2748fb7bfaSmrg  *  This file is a GNU extension to the Standard C++ Library.
2848fb7bfaSmrg  *
294fee23f9Smrg  *  @author Bob Walters
304fee23f9Smrg  *
314fee23f9Smrg  * Provides reusable _Pointer_adapter for assisting in the development of
324fee23f9Smrg  * custom pointer types that can be used with the standard containers via
334fee23f9Smrg  * the allocator::pointer and allocator::const_pointer typedefs.
344fee23f9Smrg  */
354fee23f9Smrg 
364fee23f9Smrg #ifndef _POINTER_H
374fee23f9Smrg #define _POINTER_H 1
384fee23f9Smrg 
394fee23f9Smrg #pragma GCC system_header
404fee23f9Smrg 
414fee23f9Smrg #include <iosfwd>
424fee23f9Smrg #include <bits/stl_iterator_base_types.h>
434fee23f9Smrg #include <ext/cast.h>
444fee23f9Smrg #include <ext/type_traits.h>
4548fb7bfaSmrg #if __cplusplus >= 201103L
4648fb7bfaSmrg # include <bits/move.h>
4748fb7bfaSmrg # include <bits/ptr_traits.h>
4848fb7bfaSmrg #endif
49fb8a8121Smrg #if __cplusplus > 201703L
50fb8a8121Smrg # include <iterator> // for indirectly_readable_traits
51fb8a8121Smrg #endif
524fee23f9Smrg 
_GLIBCXX_VISIBILITY(default)5348fb7bfaSmrg namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
5448fb7bfaSmrg {
5548fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
564fee23f9Smrg 
574fee23f9Smrg   /**
584fee23f9Smrg    * @brief A storage policy for use with _Pointer_adapter<> which yields a
594fee23f9Smrg    *        standard pointer.
604fee23f9Smrg    *
614fee23f9Smrg    *  A _Storage_policy is required to provide 4 things:
624fee23f9Smrg    *    1) A get() API for returning the stored pointer value.
634fee23f9Smrg    *    2) An set() API for storing a pointer value.
644fee23f9Smrg    *    3) An element_type typedef to define the type this points to.
654fee23f9Smrg    *    4) An operator<() to support pointer comparison.
664fee23f9Smrg    *    5) An operator==() to support pointer comparison.
674fee23f9Smrg    */
684fee23f9Smrg   template<typename _Tp>
694fee23f9Smrg     class _Std_pointer_impl
704fee23f9Smrg     {
714fee23f9Smrg     public:
724fee23f9Smrg       // the type this pointer points to.
734fee23f9Smrg       typedef _Tp element_type;
744fee23f9Smrg 
754fee23f9Smrg       // A method to fetch the pointer value as a standard T* value;
764fee23f9Smrg       inline _Tp*
774fee23f9Smrg       get() const
784fee23f9Smrg       { return _M_value; }
794fee23f9Smrg 
804fee23f9Smrg       // A method to set the pointer value, from a standard T* value;
814fee23f9Smrg       inline void
824fee23f9Smrg       set(element_type* __arg)
834fee23f9Smrg       { _M_value = __arg; }
844fee23f9Smrg 
854fee23f9Smrg       // Comparison of pointers
864fee23f9Smrg       inline bool
874fee23f9Smrg       operator<(const _Std_pointer_impl& __rarg) const
884fee23f9Smrg       { return (_M_value < __rarg._M_value); }
894fee23f9Smrg 
904fee23f9Smrg       inline bool
914fee23f9Smrg       operator==(const _Std_pointer_impl& __rarg) const
924fee23f9Smrg       { return (_M_value == __rarg._M_value); }
934fee23f9Smrg 
944fee23f9Smrg     private:
954fee23f9Smrg       element_type* _M_value;
964fee23f9Smrg     };
974fee23f9Smrg 
984fee23f9Smrg   /**
994fee23f9Smrg    * @brief A storage policy for use with _Pointer_adapter<> which stores
1004fee23f9Smrg    *        the pointer's address as an offset value which is relative to
1014fee23f9Smrg    *        its own address.
1024fee23f9Smrg    *
1034fee23f9Smrg    * This is intended for pointers within shared memory regions which
1044fee23f9Smrg    * might be mapped at different addresses by different processes.
1054fee23f9Smrg    * For null pointers, a value of 1 is used.  (0 is legitimate
1064fee23f9Smrg    * sometimes for nodes in circularly linked lists) This value was
1074fee23f9Smrg    * chosen as the least likely to generate an incorrect null, As
1084fee23f9Smrg    * there is no reason why any normal pointer would point 1 byte into
1094fee23f9Smrg    * its own pointer address.
1104fee23f9Smrg    */
1114fee23f9Smrg   template<typename _Tp>
1124fee23f9Smrg     class _Relative_pointer_impl
1134fee23f9Smrg     {
1144fee23f9Smrg     public:
1154fee23f9Smrg       typedef _Tp element_type;
1164fee23f9Smrg 
1174fee23f9Smrg       _Tp*
1184fee23f9Smrg       get() const
1194fee23f9Smrg       {
1204fee23f9Smrg         if (_M_diff == 1)
1214fee23f9Smrg           return 0;
1224fee23f9Smrg         else
123*b1e83836Smrg           return reinterpret_cast<_Tp*>(reinterpret_cast<uintptr_t>(this)
1244fee23f9Smrg 					+ _M_diff);
1254fee23f9Smrg       }
1264fee23f9Smrg 
1274fee23f9Smrg       void
1284fee23f9Smrg       set(_Tp* __arg)
1294fee23f9Smrg       {
1304fee23f9Smrg         if (!__arg)
1314fee23f9Smrg           _M_diff = 1;
1324fee23f9Smrg         else
133*b1e83836Smrg           _M_diff = reinterpret_cast<uintptr_t>(__arg)
134*b1e83836Smrg                     - reinterpret_cast<uintptr_t>(this);
1354fee23f9Smrg       }
1364fee23f9Smrg 
1374fee23f9Smrg       // Comparison of pointers
1384fee23f9Smrg       inline bool
1394fee23f9Smrg       operator<(const _Relative_pointer_impl& __rarg) const
140*b1e83836Smrg       { return (reinterpret_cast<uintptr_t>(this->get())
141*b1e83836Smrg 		< reinterpret_cast<uintptr_t>(__rarg.get())); }
1424fee23f9Smrg 
1434fee23f9Smrg       inline bool
1444fee23f9Smrg       operator==(const _Relative_pointer_impl& __rarg) const
145*b1e83836Smrg       { return (reinterpret_cast<uintptr_t>(this->get())
146*b1e83836Smrg 		== reinterpret_cast<uintptr_t>(__rarg.get())); }
1474fee23f9Smrg 
1484fee23f9Smrg     private:
149*b1e83836Smrg       typedef __UINTPTR_TYPE__ uintptr_t;
150*b1e83836Smrg       uintptr_t _M_diff;
1514fee23f9Smrg     };
1524fee23f9Smrg 
1534fee23f9Smrg   /**
1544fee23f9Smrg    * Relative_pointer_impl needs a specialization for const T because of
1554fee23f9Smrg    * the casting done during pointer arithmetic.
1564fee23f9Smrg    */
1574fee23f9Smrg   template<typename _Tp>
1584fee23f9Smrg     class _Relative_pointer_impl<const _Tp>
1594fee23f9Smrg     {
1604fee23f9Smrg     public:
1614fee23f9Smrg       typedef const _Tp element_type;
1624fee23f9Smrg 
1634fee23f9Smrg       const _Tp*
1644fee23f9Smrg       get() const
1654fee23f9Smrg       {
1664fee23f9Smrg         if (_M_diff == 1)
1674fee23f9Smrg           return 0;
1684fee23f9Smrg         else
1694fee23f9Smrg           return reinterpret_cast<const _Tp*>
170*b1e83836Smrg 	      (reinterpret_cast<uintptr_t>(this) + _M_diff);
1714fee23f9Smrg       }
1724fee23f9Smrg 
1734fee23f9Smrg       void
1744fee23f9Smrg       set(const _Tp* __arg)
1754fee23f9Smrg       {
1764fee23f9Smrg         if (!__arg)
1774fee23f9Smrg           _M_diff = 1;
1784fee23f9Smrg         else
179*b1e83836Smrg           _M_diff = reinterpret_cast<uintptr_t>(__arg)
180*b1e83836Smrg                     - reinterpret_cast<uintptr_t>(this);
1814fee23f9Smrg       }
1824fee23f9Smrg 
1834fee23f9Smrg       // Comparison of pointers
1844fee23f9Smrg       inline bool
1854fee23f9Smrg       operator<(const _Relative_pointer_impl& __rarg) const
186*b1e83836Smrg       { return (reinterpret_cast<uintptr_t>(this->get())
187*b1e83836Smrg 		< reinterpret_cast<uintptr_t>(__rarg.get())); }
1884fee23f9Smrg 
1894fee23f9Smrg       inline bool
1904fee23f9Smrg       operator==(const _Relative_pointer_impl& __rarg) const
191*b1e83836Smrg       { return (reinterpret_cast<uintptr_t>(this->get())
192*b1e83836Smrg 		== reinterpret_cast<uintptr_t>(__rarg.get())); }
1934fee23f9Smrg 
1944fee23f9Smrg     private:
195*b1e83836Smrg       typedef __UINTPTR_TYPE__ uintptr_t;
196*b1e83836Smrg       uintptr_t _M_diff;
1974fee23f9Smrg     };
1984fee23f9Smrg 
1994fee23f9Smrg   /**
2004fee23f9Smrg    * The specialization on this type helps resolve the problem of
2014fee23f9Smrg    * reference to void, and eliminates the need to specialize
2024fee23f9Smrg    * _Pointer_adapter for cases of void*, const void*, and so on.
2034fee23f9Smrg    */
2044fee23f9Smrg   struct _Invalid_type { };
2054fee23f9Smrg 
2064fee23f9Smrg   template<typename _Tp>
2074fee23f9Smrg     struct _Reference_type
2084fee23f9Smrg     { typedef _Tp& reference; };
2094fee23f9Smrg 
2104fee23f9Smrg   template<>
2114fee23f9Smrg     struct _Reference_type<void>
2124fee23f9Smrg     { typedef _Invalid_type& reference; };
2134fee23f9Smrg 
2144fee23f9Smrg   template<>
2154fee23f9Smrg     struct _Reference_type<const void>
2164fee23f9Smrg     { typedef const _Invalid_type& reference; };
2174fee23f9Smrg 
2184fee23f9Smrg   template<>
2194fee23f9Smrg     struct _Reference_type<volatile void>
2204fee23f9Smrg     { typedef volatile _Invalid_type&  reference; };
2214fee23f9Smrg 
2224fee23f9Smrg   template<>
2234fee23f9Smrg     struct _Reference_type<volatile const void>
2244fee23f9Smrg     { typedef const volatile _Invalid_type&  reference; };
2254fee23f9Smrg 
2264fee23f9Smrg   /**
22748fb7bfaSmrg    * This structure accommodates the way in which
2284fee23f9Smrg    * std::iterator_traits<> is normally specialized for const T*, so
2294fee23f9Smrg    * that value_type is still T.
2304fee23f9Smrg    */
2314fee23f9Smrg   template<typename _Tp>
2324fee23f9Smrg     struct _Unqualified_type
2334fee23f9Smrg     { typedef _Tp type; };
2344fee23f9Smrg 
2354fee23f9Smrg   template<typename _Tp>
2364fee23f9Smrg     struct _Unqualified_type<const _Tp>
2374fee23f9Smrg     { typedef _Tp type; };
2384fee23f9Smrg 
2394fee23f9Smrg   /**
2404fee23f9Smrg    * The following provides an 'alternative pointer' that works with
2414fee23f9Smrg    * the containers when specified as the pointer typedef of the
2424fee23f9Smrg    * allocator.
2434fee23f9Smrg    *
2444fee23f9Smrg    * The pointer type used with the containers doesn't have to be this
2454fee23f9Smrg    * class, but it must support the implicit conversions, pointer
2464fee23f9Smrg    * arithmetic, comparison operators, etc. that are supported by this
2474fee23f9Smrg    * class, and avoid raising compile-time ambiguities.  Because
2484fee23f9Smrg    * creating a working pointer can be challenging, this pointer
2494fee23f9Smrg    * template was designed to wrapper an easier storage policy type,
2504fee23f9Smrg    * so that it becomes reusable for creating other pointer types.
2514fee23f9Smrg    *
2524fee23f9Smrg    * A key point of this class is also that it allows container
25348fb7bfaSmrg    * writers to 'assume' Allocator::pointer is a typedef for a normal
2544fee23f9Smrg    * pointer.  This class supports most of the conventions of a true
2554fee23f9Smrg    * pointer, and can, for instance handle implicit conversion to
2564fee23f9Smrg    * const and base class pointer types.  The only impositions on
2574fee23f9Smrg    * container writers to support extended pointers are: 1) use the
2584fee23f9Smrg    * Allocator::pointer typedef appropriately for pointer types.  2)
2594fee23f9Smrg    * if you need pointer casting, use the __pointer_cast<> functions
2604fee23f9Smrg    * from ext/cast.h.  This allows pointer cast operations to be
26148fb7bfaSmrg    * overloaded as necessary by custom pointers.
2624fee23f9Smrg    *
2634fee23f9Smrg    * Note: The const qualifier works with this pointer adapter as
2644fee23f9Smrg    * follows:
2654fee23f9Smrg    *
2664fee23f9Smrg    * _Tp*             == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
2674fee23f9Smrg    * const _Tp*       == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
2684fee23f9Smrg    * _Tp* const       == const _Pointer_adapter<_Std_pointer_impl<_Tp> >;
2694fee23f9Smrg    * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
2704fee23f9Smrg    */
2714fee23f9Smrg   template<typename _Storage_policy>
2724fee23f9Smrg     class _Pointer_adapter : public _Storage_policy
2734fee23f9Smrg     {
2744fee23f9Smrg     public:
2754fee23f9Smrg       typedef typename _Storage_policy::element_type element_type;
2764fee23f9Smrg 
2774fee23f9Smrg       // These are needed for iterator_traits
2784fee23f9Smrg       typedef std::random_access_iterator_tag                iterator_category;
2794fee23f9Smrg       typedef typename _Unqualified_type<element_type>::type value_type;
2804fee23f9Smrg       typedef std::ptrdiff_t                                 difference_type;
2814fee23f9Smrg       typedef _Pointer_adapter                               pointer;
2824fee23f9Smrg       typedef typename _Reference_type<element_type>::reference  reference;
2834fee23f9Smrg 
2844fee23f9Smrg       // Reminder: 'const' methods mean that the method is valid when the
2854fee23f9Smrg       // pointer is immutable, and has nothing to do with whether the
2864fee23f9Smrg       // 'pointee' is const.
2874fee23f9Smrg 
2884fee23f9Smrg       // Default Constructor (Convert from element_type*)
2894fee23f9Smrg       _Pointer_adapter(element_type* __arg = 0)
2904fee23f9Smrg       { _Storage_policy::set(__arg); }
2914fee23f9Smrg 
2924fee23f9Smrg       // Copy constructor from _Pointer_adapter of same type.
2934fee23f9Smrg       _Pointer_adapter(const _Pointer_adapter& __arg)
2944fee23f9Smrg       { _Storage_policy::set(__arg.get()); }
2954fee23f9Smrg 
2964fee23f9Smrg       // Convert from _Up* if conversion to element_type* is valid.
2974fee23f9Smrg       template<typename _Up>
2984fee23f9Smrg         _Pointer_adapter(_Up* __arg)
2994fee23f9Smrg         { _Storage_policy::set(__arg); }
3004fee23f9Smrg 
3014fee23f9Smrg       // Conversion from another _Pointer_adapter if _Up if static cast is
3024fee23f9Smrg       // valid.
3034fee23f9Smrg       template<typename _Up>
3044fee23f9Smrg         _Pointer_adapter(const _Pointer_adapter<_Up>& __arg)
3054fee23f9Smrg         { _Storage_policy::set(__arg.get()); }
3064fee23f9Smrg 
3074fee23f9Smrg       // Destructor
3084fee23f9Smrg       ~_Pointer_adapter() { }
3094fee23f9Smrg 
3104fee23f9Smrg       // Assignment operator
3114fee23f9Smrg       _Pointer_adapter&
3124fee23f9Smrg       operator=(const _Pointer_adapter& __arg)
3134fee23f9Smrg       {
3144fee23f9Smrg         _Storage_policy::set(__arg.get());
3154fee23f9Smrg         return *this;
3164fee23f9Smrg       }
3174fee23f9Smrg 
3184fee23f9Smrg       template<typename _Up>
3194fee23f9Smrg         _Pointer_adapter&
3204fee23f9Smrg         operator=(const _Pointer_adapter<_Up>& __arg)
3214fee23f9Smrg         {
3224fee23f9Smrg           _Storage_policy::set(__arg.get());
3234fee23f9Smrg           return *this;
3244fee23f9Smrg         }
3254fee23f9Smrg 
3264fee23f9Smrg       template<typename _Up>
3274fee23f9Smrg         _Pointer_adapter&
3284fee23f9Smrg         operator=(_Up* __arg)
3294fee23f9Smrg         {
3304fee23f9Smrg           _Storage_policy::set(__arg);
3314fee23f9Smrg           return *this;
3324fee23f9Smrg         }
3334fee23f9Smrg 
3344fee23f9Smrg       // Operator*, returns element_type&
3354fee23f9Smrg       inline reference
3364fee23f9Smrg       operator*() const
3374fee23f9Smrg       { return *(_Storage_policy::get()); }
3384fee23f9Smrg 
3394fee23f9Smrg       // Operator->, returns element_type*
3404fee23f9Smrg       inline element_type*
3414fee23f9Smrg       operator->() const
3424fee23f9Smrg       { return _Storage_policy::get(); }
3434fee23f9Smrg 
3444fee23f9Smrg       // Operator[], returns a element_type& to the item at that loc.
3454fee23f9Smrg       inline reference
3464fee23f9Smrg       operator[](std::ptrdiff_t __index) const
3474fee23f9Smrg       { return _Storage_policy::get()[__index]; }
3484fee23f9Smrg 
3494fee23f9Smrg       // To allow implicit conversion to "bool", for "if (ptr)..."
350181254a7Smrg #if __cplusplus >= 201103L
351181254a7Smrg       explicit operator bool() const { return _Storage_policy::get() != 0; }
352181254a7Smrg #else
3534fee23f9Smrg     private:
3544fee23f9Smrg       typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;
3554fee23f9Smrg 
3564fee23f9Smrg     public:
3574fee23f9Smrg       operator __unspecified_bool_type() const
3584fee23f9Smrg       {
3594fee23f9Smrg         return _Storage_policy::get() == 0 ? 0 :
3604fee23f9Smrg                          &_Pointer_adapter::operator->;
3614fee23f9Smrg       }
3624fee23f9Smrg 
3634fee23f9Smrg       // ! operator (for: if (!ptr)...)
3644fee23f9Smrg       inline bool
3654fee23f9Smrg       operator!() const
3664fee23f9Smrg       { return (_Storage_policy::get() == 0); }
367181254a7Smrg #endif
3684fee23f9Smrg 
3694fee23f9Smrg       // Pointer differences
3704fee23f9Smrg       inline friend std::ptrdiff_t
3714fee23f9Smrg       operator-(const _Pointer_adapter& __lhs, element_type* __rhs)
3724fee23f9Smrg       { return (__lhs.get() - __rhs); }
3734fee23f9Smrg 
3744fee23f9Smrg       inline friend std::ptrdiff_t
3754fee23f9Smrg       operator-(element_type* __lhs, const _Pointer_adapter& __rhs)
3764fee23f9Smrg       { return (__lhs - __rhs.get()); }
3774fee23f9Smrg 
3784fee23f9Smrg       template<typename _Up>
3794fee23f9Smrg         inline friend std::ptrdiff_t
3804fee23f9Smrg         operator-(const _Pointer_adapter& __lhs, _Up* __rhs)
3814fee23f9Smrg         { return (__lhs.get() - __rhs); }
3824fee23f9Smrg 
3834fee23f9Smrg       template<typename _Up>
3844fee23f9Smrg         inline friend std::ptrdiff_t
3854fee23f9Smrg         operator-(_Up* __lhs, const _Pointer_adapter& __rhs)
3864fee23f9Smrg         { return (__lhs - __rhs.get()); }
3874fee23f9Smrg 
3884fee23f9Smrg       template<typename _Up>
3894fee23f9Smrg         inline std::ptrdiff_t
3904fee23f9Smrg         operator-(const _Pointer_adapter<_Up>& __rhs) const
3914fee23f9Smrg         { return (_Storage_policy::get() - __rhs.get()); }
3924fee23f9Smrg 
3934fee23f9Smrg       // Pointer math
3944fee23f9Smrg       // Note: There is a reason for all this overloading based on different
3954fee23f9Smrg       // integer types.  In some libstdc++-v3 test cases, a templated
3964fee23f9Smrg       // operator+ is declared which can match any types.  This operator
3974fee23f9Smrg       // tends to "steal" the recognition of _Pointer_adapter's own operator+
3984fee23f9Smrg       // unless the integer type matches perfectly.
3994fee23f9Smrg 
4004fee23f9Smrg #define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \
4014fee23f9Smrg       inline friend _Pointer_adapter \
4024fee23f9Smrg       operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
4034fee23f9Smrg       { return _Pointer_adapter(__lhs.get() + __offset); } \
4044fee23f9Smrg \
4054fee23f9Smrg       inline friend _Pointer_adapter \
4064fee23f9Smrg       operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \
4074fee23f9Smrg       { return _Pointer_adapter(__rhs.get() + __offset); } \
4084fee23f9Smrg \
4094fee23f9Smrg       inline friend _Pointer_adapter \
4104fee23f9Smrg       operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
4114fee23f9Smrg       { return _Pointer_adapter(__lhs.get() - __offset); } \
4124fee23f9Smrg \
4134fee23f9Smrg       inline _Pointer_adapter& \
4144fee23f9Smrg       operator+=(INT_TYPE __offset) \
4154fee23f9Smrg       { \
4164fee23f9Smrg         _Storage_policy::set(_Storage_policy::get() + __offset); \
4174fee23f9Smrg         return *this; \
4184fee23f9Smrg       } \
4194fee23f9Smrg \
4204fee23f9Smrg       inline _Pointer_adapter& \
4214fee23f9Smrg       operator-=(INT_TYPE __offset) \
4224fee23f9Smrg       { \
4234fee23f9Smrg         _Storage_policy::set(_Storage_policy::get() - __offset); \
4244fee23f9Smrg         return *this; \
4254fee23f9Smrg       } \
4264fee23f9Smrg // END of _CXX_POINTER_ARITH_OPERATOR_SET macro
4274fee23f9Smrg 
42848fb7bfaSmrg       // Expand into the various pointer arithmetic operators needed.
4294fee23f9Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(short);
4304fee23f9Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
4314fee23f9Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(int);
4324fee23f9Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
4334fee23f9Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(long);
4344fee23f9Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
435d79abf08Smrg #ifdef _GLIBCXX_USE_LONG_LONG
436d79abf08Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(long long);
437d79abf08Smrg       _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long);
438d79abf08Smrg #endif
4394fee23f9Smrg 
4404fee23f9Smrg       // Mathematical Manipulators
4414fee23f9Smrg       inline _Pointer_adapter&
4424fee23f9Smrg       operator++()
4434fee23f9Smrg       {
4444fee23f9Smrg         _Storage_policy::set(_Storage_policy::get() + 1);
4454fee23f9Smrg         return *this;
4464fee23f9Smrg       }
4474fee23f9Smrg 
4484fee23f9Smrg       inline _Pointer_adapter
44948fb7bfaSmrg       operator++(int)
4504fee23f9Smrg       {
4513f4ceed9Smrg         _Pointer_adapter __tmp(*this);
4524fee23f9Smrg         _Storage_policy::set(_Storage_policy::get() + 1);
4533f4ceed9Smrg         return __tmp;
4544fee23f9Smrg       }
4554fee23f9Smrg 
4564fee23f9Smrg       inline _Pointer_adapter&
4574fee23f9Smrg       operator--()
4584fee23f9Smrg       {
4594fee23f9Smrg         _Storage_policy::set(_Storage_policy::get() - 1);
4604fee23f9Smrg         return *this;
4614fee23f9Smrg       }
4624fee23f9Smrg 
4634fee23f9Smrg       inline _Pointer_adapter
4644fee23f9Smrg       operator--(int)
4654fee23f9Smrg       {
4663f4ceed9Smrg         _Pointer_adapter __tmp(*this);
4674fee23f9Smrg         _Storage_policy::set(_Storage_policy::get() - 1);
4683f4ceed9Smrg         return __tmp;
4694fee23f9Smrg       }
4704fee23f9Smrg 
471fb8a8121Smrg #if __cpp_lib_three_way_comparison
472fb8a8121Smrg       friend std::strong_ordering
473fb8a8121Smrg       operator<=>(const _Pointer_adapter& __lhs, const _Pointer_adapter& __rhs)
474fb8a8121Smrg       noexcept
475fb8a8121Smrg       { return __lhs.get() <=> __rhs.get(); }
476fb8a8121Smrg #endif
4774fee23f9Smrg     }; // class _Pointer_adapter
4784fee23f9Smrg 
4794fee23f9Smrg 
4804fee23f9Smrg #define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \
4814fee23f9Smrg   template<typename _Tp1, typename _Tp2> \
4824fee23f9Smrg     inline bool \
4834fee23f9Smrg     operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
4844fee23f9Smrg     { return __lhs.get() OPERATOR __rhs; } \
4854fee23f9Smrg \
4864fee23f9Smrg   template<typename _Tp1, typename _Tp2> \
4874fee23f9Smrg     inline bool \
4884fee23f9Smrg     operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
4894fee23f9Smrg     { return __lhs OPERATOR __rhs.get(); } \
4904fee23f9Smrg \
4914fee23f9Smrg   template<typename _Tp1, typename _Tp2> \
4924fee23f9Smrg     inline bool \
4934fee23f9Smrg     operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \
4944fee23f9Smrg                               const _Pointer_adapter<_Tp2>& __rhs) \
4954fee23f9Smrg     { return __lhs.get() OPERATOR __rhs.get(); } \
4964fee23f9Smrg \
4974fee23f9Smrg // End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro
4984fee23f9Smrg 
4994fee23f9Smrg   // Expand into the various comparison operators needed.
5004fee23f9Smrg   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==)
5014fee23f9Smrg   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=)
5024fee23f9Smrg   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<)
5034fee23f9Smrg   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=)
5044fee23f9Smrg   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>)
5054fee23f9Smrg   _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=)
5064fee23f9Smrg 
5074fee23f9Smrg   // These are here for expressions like "ptr == 0", "ptr != 0"
5084fee23f9Smrg   template<typename _Tp>
5094fee23f9Smrg     inline bool
5104fee23f9Smrg     operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
5114fee23f9Smrg     { return __lhs.get() == reinterpret_cast<void*>(__rhs); }
5124fee23f9Smrg 
5134fee23f9Smrg   template<typename _Tp>
5144fee23f9Smrg     inline bool
5154fee23f9Smrg     operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
5164fee23f9Smrg     { return __rhs.get() == reinterpret_cast<void*>(__lhs); }
5174fee23f9Smrg 
5184fee23f9Smrg   template<typename _Tp>
5194fee23f9Smrg     inline bool
5204fee23f9Smrg     operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
5214fee23f9Smrg     { return __lhs.get() != reinterpret_cast<void*>(__rhs); }
5224fee23f9Smrg 
5234fee23f9Smrg   template<typename _Tp>
5244fee23f9Smrg     inline bool
5254fee23f9Smrg     operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
5264fee23f9Smrg     { return __rhs.get() != reinterpret_cast<void*>(__lhs); }
5274fee23f9Smrg 
5284fee23f9Smrg   /**
52948fb7bfaSmrg    * Comparison operators for _Pointer_adapter defer to the base class'
5304fee23f9Smrg    * comparison operators, when possible.
5314fee23f9Smrg    */
5324fee23f9Smrg   template<typename _Tp>
5334fee23f9Smrg     inline bool
5344fee23f9Smrg     operator==(const _Pointer_adapter<_Tp>& __lhs,
5354fee23f9Smrg                const _Pointer_adapter<_Tp>& __rhs)
5364fee23f9Smrg     { return __lhs._Tp::operator==(__rhs); }
5374fee23f9Smrg 
5384fee23f9Smrg   template<typename _Tp>
5394fee23f9Smrg     inline bool
5404fee23f9Smrg     operator<=(const _Pointer_adapter<_Tp>& __lhs,
5414fee23f9Smrg                const _Pointer_adapter<_Tp>& __rhs)
5424fee23f9Smrg     { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); }
5434fee23f9Smrg 
5444fee23f9Smrg   template<typename _Tp>
5454fee23f9Smrg     inline bool
5464fee23f9Smrg     operator!=(const _Pointer_adapter<_Tp>& __lhs,
5474fee23f9Smrg                const _Pointer_adapter<_Tp>& __rhs)
5484fee23f9Smrg     { return !(__lhs._Tp::operator==(__rhs)); }
5494fee23f9Smrg 
5504fee23f9Smrg   template<typename _Tp>
5514fee23f9Smrg     inline bool
5524fee23f9Smrg     operator>(const _Pointer_adapter<_Tp>& __lhs,
5534fee23f9Smrg               const _Pointer_adapter<_Tp>& __rhs)
5544fee23f9Smrg     { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); }
5554fee23f9Smrg 
5564fee23f9Smrg   template<typename _Tp>
5574fee23f9Smrg     inline bool
5584fee23f9Smrg     operator>=(const _Pointer_adapter<_Tp>& __lhs,
5594fee23f9Smrg                const _Pointer_adapter<_Tp>& __rhs)
5604fee23f9Smrg     { return !(__lhs._Tp::operator<(__rhs)); }
5614fee23f9Smrg 
5624fee23f9Smrg   template<typename _CharT, typename _Traits, typename _StoreT>
5634fee23f9Smrg     inline std::basic_ostream<_CharT, _Traits>&
5644fee23f9Smrg     operator<<(std::basic_ostream<_CharT, _Traits>& __os,
5654fee23f9Smrg                const _Pointer_adapter<_StoreT>& __p)
5664fee23f9Smrg     { return (__os << __p.get()); }
5674fee23f9Smrg 
56848fb7bfaSmrg _GLIBCXX_END_NAMESPACE_VERSION
56948fb7bfaSmrg } // namespace
57048fb7bfaSmrg 
57148fb7bfaSmrg #if __cplusplus >= 201103L
57248fb7bfaSmrg namespace std _GLIBCXX_VISIBILITY(default)
57348fb7bfaSmrg {
57448fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
57548fb7bfaSmrg 
57648fb7bfaSmrg   template<typename _Storage_policy>
57748fb7bfaSmrg     struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
57848fb7bfaSmrg     {
57948fb7bfaSmrg       /// The pointer type
58048fb7bfaSmrg       typedef __gnu_cxx::_Pointer_adapter<_Storage_policy>         pointer;
58148fb7bfaSmrg       /// The type pointed to
58248fb7bfaSmrg       typedef typename pointer::element_type            element_type;
58348fb7bfaSmrg       /// Type used to represent the difference between two pointers
58448fb7bfaSmrg       typedef typename pointer::difference_type         difference_type;
58548fb7bfaSmrg 
58648fb7bfaSmrg       template<typename _Up>
58748fb7bfaSmrg         using rebind = typename __gnu_cxx::_Pointer_adapter<
5884d5abbe8Smrg 	  typename pointer_traits<_Storage_policy>::template rebind<_Up>>;
58948fb7bfaSmrg 
59048fb7bfaSmrg       static pointer pointer_to(typename pointer::reference __r) noexcept
59148fb7bfaSmrg       { return pointer(std::addressof(__r)); }
59248fb7bfaSmrg     };
59348fb7bfaSmrg 
594fb8a8121Smrg #if __cpp_lib_concepts
595fb8a8121Smrg   template<typename _Policy>
596fb8a8121Smrg     struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>>
597fb8a8121Smrg     {
598fb8a8121Smrg       using value_type
599fb8a8121Smrg 	= typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type;
600fb8a8121Smrg     };
601fb8a8121Smrg #endif
60248fb7bfaSmrg _GLIBCXX_END_NAMESPACE_VERSION
60348fb7bfaSmrg } // namespace
60448fb7bfaSmrg #endif
6054fee23f9Smrg 
6064fee23f9Smrg #endif // _POINTER_H
607