136ac495dSmrg // Custom pointer adapter and sample storage policies
236ac495dSmrg
3*8feb0f0bSmrg // Copyright (C) 2008-2020 Free Software Foundation, Inc.
436ac495dSmrg //
536ac495dSmrg // This file is part of the GNU ISO C++ Library. This library is free
636ac495dSmrg // software; you can redistribute it and/or modify it under the
736ac495dSmrg // terms of the GNU General Public License as published by the
836ac495dSmrg // Free Software Foundation; either version 3, or (at your option)
936ac495dSmrg // any later version.
1036ac495dSmrg
1136ac495dSmrg // This library is distributed in the hope that it will be useful,
1236ac495dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1436ac495dSmrg // GNU General Public License for more details.
1536ac495dSmrg
1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg // 3.1, as published by the Free Software Foundation.
1936ac495dSmrg
2036ac495dSmrg // You should have received a copy of the GNU General Public License and
2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2336ac495dSmrg // <http://www.gnu.org/licenses/>.
2436ac495dSmrg
2536ac495dSmrg /**
2636ac495dSmrg * @file ext/pointer.h
2736ac495dSmrg * This file is a GNU extension to the Standard C++ Library.
2836ac495dSmrg *
2936ac495dSmrg * @author Bob Walters
3036ac495dSmrg *
3136ac495dSmrg * Provides reusable _Pointer_adapter for assisting in the development of
3236ac495dSmrg * custom pointer types that can be used with the standard containers via
3336ac495dSmrg * the allocator::pointer and allocator::const_pointer typedefs.
3436ac495dSmrg */
3536ac495dSmrg
3636ac495dSmrg #ifndef _POINTER_H
3736ac495dSmrg #define _POINTER_H 1
3836ac495dSmrg
3936ac495dSmrg #pragma GCC system_header
4036ac495dSmrg
4136ac495dSmrg #include <iosfwd>
4236ac495dSmrg #include <bits/stl_iterator_base_types.h>
4336ac495dSmrg #include <ext/cast.h>
4436ac495dSmrg #include <ext/type_traits.h>
4536ac495dSmrg #if __cplusplus >= 201103L
4636ac495dSmrg # include <bits/move.h>
4736ac495dSmrg # include <bits/ptr_traits.h>
4836ac495dSmrg #endif
49*8feb0f0bSmrg #if __cplusplus > 201703L
50*8feb0f0bSmrg # include <iterator> // for indirectly_readable_traits
51*8feb0f0bSmrg #endif
5236ac495dSmrg
_GLIBCXX_VISIBILITY(default)5336ac495dSmrg namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
5436ac495dSmrg {
5536ac495dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
5636ac495dSmrg
5736ac495dSmrg /**
5836ac495dSmrg * @brief A storage policy for use with _Pointer_adapter<> which yields a
5936ac495dSmrg * standard pointer.
6036ac495dSmrg *
6136ac495dSmrg * A _Storage_policy is required to provide 4 things:
6236ac495dSmrg * 1) A get() API for returning the stored pointer value.
6336ac495dSmrg * 2) An set() API for storing a pointer value.
6436ac495dSmrg * 3) An element_type typedef to define the type this points to.
6536ac495dSmrg * 4) An operator<() to support pointer comparison.
6636ac495dSmrg * 5) An operator==() to support pointer comparison.
6736ac495dSmrg */
6836ac495dSmrg template<typename _Tp>
6936ac495dSmrg class _Std_pointer_impl
7036ac495dSmrg {
7136ac495dSmrg public:
7236ac495dSmrg // the type this pointer points to.
7336ac495dSmrg typedef _Tp element_type;
7436ac495dSmrg
7536ac495dSmrg // A method to fetch the pointer value as a standard T* value;
7636ac495dSmrg inline _Tp*
7736ac495dSmrg get() const
7836ac495dSmrg { return _M_value; }
7936ac495dSmrg
8036ac495dSmrg // A method to set the pointer value, from a standard T* value;
8136ac495dSmrg inline void
8236ac495dSmrg set(element_type* __arg)
8336ac495dSmrg { _M_value = __arg; }
8436ac495dSmrg
8536ac495dSmrg // Comparison of pointers
8636ac495dSmrg inline bool
8736ac495dSmrg operator<(const _Std_pointer_impl& __rarg) const
8836ac495dSmrg { return (_M_value < __rarg._M_value); }
8936ac495dSmrg
9036ac495dSmrg inline bool
9136ac495dSmrg operator==(const _Std_pointer_impl& __rarg) const
9236ac495dSmrg { return (_M_value == __rarg._M_value); }
9336ac495dSmrg
9436ac495dSmrg private:
9536ac495dSmrg element_type* _M_value;
9636ac495dSmrg };
9736ac495dSmrg
9836ac495dSmrg /**
9936ac495dSmrg * @brief A storage policy for use with _Pointer_adapter<> which stores
10036ac495dSmrg * the pointer's address as an offset value which is relative to
10136ac495dSmrg * its own address.
10236ac495dSmrg *
10336ac495dSmrg * This is intended for pointers within shared memory regions which
10436ac495dSmrg * might be mapped at different addresses by different processes.
10536ac495dSmrg * For null pointers, a value of 1 is used. (0 is legitimate
10636ac495dSmrg * sometimes for nodes in circularly linked lists) This value was
10736ac495dSmrg * chosen as the least likely to generate an incorrect null, As
10836ac495dSmrg * there is no reason why any normal pointer would point 1 byte into
10936ac495dSmrg * its own pointer address.
11036ac495dSmrg */
11136ac495dSmrg template<typename _Tp>
11236ac495dSmrg class _Relative_pointer_impl
11336ac495dSmrg {
11436ac495dSmrg public:
11536ac495dSmrg typedef _Tp element_type;
11636ac495dSmrg
11736ac495dSmrg _Tp*
11836ac495dSmrg get() const
11936ac495dSmrg {
12036ac495dSmrg if (_M_diff == 1)
12136ac495dSmrg return 0;
12236ac495dSmrg else
12336ac495dSmrg return reinterpret_cast<_Tp*>(reinterpret_cast<_UIntPtrType>(this)
12436ac495dSmrg + _M_diff);
12536ac495dSmrg }
12636ac495dSmrg
12736ac495dSmrg void
12836ac495dSmrg set(_Tp* __arg)
12936ac495dSmrg {
13036ac495dSmrg if (!__arg)
13136ac495dSmrg _M_diff = 1;
13236ac495dSmrg else
13336ac495dSmrg _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
13436ac495dSmrg - reinterpret_cast<_UIntPtrType>(this);
13536ac495dSmrg }
13636ac495dSmrg
13736ac495dSmrg // Comparison of pointers
13836ac495dSmrg inline bool
13936ac495dSmrg operator<(const _Relative_pointer_impl& __rarg) const
14036ac495dSmrg { return (reinterpret_cast<_UIntPtrType>(this->get())
14136ac495dSmrg < reinterpret_cast<_UIntPtrType>(__rarg.get())); }
14236ac495dSmrg
14336ac495dSmrg inline bool
14436ac495dSmrg operator==(const _Relative_pointer_impl& __rarg) const
14536ac495dSmrg { return (reinterpret_cast<_UIntPtrType>(this->get())
14636ac495dSmrg == reinterpret_cast<_UIntPtrType>(__rarg.get())); }
14736ac495dSmrg
14836ac495dSmrg private:
14936ac495dSmrg #ifdef _GLIBCXX_USE_LONG_LONG
15036ac495dSmrg typedef __gnu_cxx::__conditional_type<
15136ac495dSmrg (sizeof(unsigned long) >= sizeof(void*)),
15236ac495dSmrg unsigned long, unsigned long long>::__type _UIntPtrType;
15336ac495dSmrg #else
15436ac495dSmrg typedef unsigned long _UIntPtrType;
15536ac495dSmrg #endif
15636ac495dSmrg _UIntPtrType _M_diff;
15736ac495dSmrg };
15836ac495dSmrg
15936ac495dSmrg /**
16036ac495dSmrg * Relative_pointer_impl needs a specialization for const T because of
16136ac495dSmrg * the casting done during pointer arithmetic.
16236ac495dSmrg */
16336ac495dSmrg template<typename _Tp>
16436ac495dSmrg class _Relative_pointer_impl<const _Tp>
16536ac495dSmrg {
16636ac495dSmrg public:
16736ac495dSmrg typedef const _Tp element_type;
16836ac495dSmrg
16936ac495dSmrg const _Tp*
17036ac495dSmrg get() const
17136ac495dSmrg {
17236ac495dSmrg if (_M_diff == 1)
17336ac495dSmrg return 0;
17436ac495dSmrg else
17536ac495dSmrg return reinterpret_cast<const _Tp*>
17636ac495dSmrg (reinterpret_cast<_UIntPtrType>(this) + _M_diff);
17736ac495dSmrg }
17836ac495dSmrg
17936ac495dSmrg void
18036ac495dSmrg set(const _Tp* __arg)
18136ac495dSmrg {
18236ac495dSmrg if (!__arg)
18336ac495dSmrg _M_diff = 1;
18436ac495dSmrg else
18536ac495dSmrg _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
18636ac495dSmrg - reinterpret_cast<_UIntPtrType>(this);
18736ac495dSmrg }
18836ac495dSmrg
18936ac495dSmrg // Comparison of pointers
19036ac495dSmrg inline bool
19136ac495dSmrg operator<(const _Relative_pointer_impl& __rarg) const
19236ac495dSmrg { return (reinterpret_cast<_UIntPtrType>(this->get())
19336ac495dSmrg < reinterpret_cast<_UIntPtrType>(__rarg.get())); }
19436ac495dSmrg
19536ac495dSmrg inline bool
19636ac495dSmrg operator==(const _Relative_pointer_impl& __rarg) const
19736ac495dSmrg { return (reinterpret_cast<_UIntPtrType>(this->get())
19836ac495dSmrg == reinterpret_cast<_UIntPtrType>(__rarg.get())); }
19936ac495dSmrg
20036ac495dSmrg private:
20136ac495dSmrg #ifdef _GLIBCXX_USE_LONG_LONG
20236ac495dSmrg typedef __gnu_cxx::__conditional_type<
20336ac495dSmrg (sizeof(unsigned long) >= sizeof(void*)),
20436ac495dSmrg unsigned long, unsigned long long>::__type _UIntPtrType;
20536ac495dSmrg #else
20636ac495dSmrg typedef unsigned long _UIntPtrType;
20736ac495dSmrg #endif
20836ac495dSmrg _UIntPtrType _M_diff;
20936ac495dSmrg };
21036ac495dSmrg
21136ac495dSmrg /**
21236ac495dSmrg * The specialization on this type helps resolve the problem of
21336ac495dSmrg * reference to void, and eliminates the need to specialize
21436ac495dSmrg * _Pointer_adapter for cases of void*, const void*, and so on.
21536ac495dSmrg */
21636ac495dSmrg struct _Invalid_type { };
21736ac495dSmrg
21836ac495dSmrg template<typename _Tp>
21936ac495dSmrg struct _Reference_type
22036ac495dSmrg { typedef _Tp& reference; };
22136ac495dSmrg
22236ac495dSmrg template<>
22336ac495dSmrg struct _Reference_type<void>
22436ac495dSmrg { typedef _Invalid_type& reference; };
22536ac495dSmrg
22636ac495dSmrg template<>
22736ac495dSmrg struct _Reference_type<const void>
22836ac495dSmrg { typedef const _Invalid_type& reference; };
22936ac495dSmrg
23036ac495dSmrg template<>
23136ac495dSmrg struct _Reference_type<volatile void>
23236ac495dSmrg { typedef volatile _Invalid_type& reference; };
23336ac495dSmrg
23436ac495dSmrg template<>
23536ac495dSmrg struct _Reference_type<volatile const void>
23636ac495dSmrg { typedef const volatile _Invalid_type& reference; };
23736ac495dSmrg
23836ac495dSmrg /**
23936ac495dSmrg * This structure accommodates the way in which
24036ac495dSmrg * std::iterator_traits<> is normally specialized for const T*, so
24136ac495dSmrg * that value_type is still T.
24236ac495dSmrg */
24336ac495dSmrg template<typename _Tp>
24436ac495dSmrg struct _Unqualified_type
24536ac495dSmrg { typedef _Tp type; };
24636ac495dSmrg
24736ac495dSmrg template<typename _Tp>
24836ac495dSmrg struct _Unqualified_type<const _Tp>
24936ac495dSmrg { typedef _Tp type; };
25036ac495dSmrg
25136ac495dSmrg /**
25236ac495dSmrg * The following provides an 'alternative pointer' that works with
25336ac495dSmrg * the containers when specified as the pointer typedef of the
25436ac495dSmrg * allocator.
25536ac495dSmrg *
25636ac495dSmrg * The pointer type used with the containers doesn't have to be this
25736ac495dSmrg * class, but it must support the implicit conversions, pointer
25836ac495dSmrg * arithmetic, comparison operators, etc. that are supported by this
25936ac495dSmrg * class, and avoid raising compile-time ambiguities. Because
26036ac495dSmrg * creating a working pointer can be challenging, this pointer
26136ac495dSmrg * template was designed to wrapper an easier storage policy type,
26236ac495dSmrg * so that it becomes reusable for creating other pointer types.
26336ac495dSmrg *
26436ac495dSmrg * A key point of this class is also that it allows container
26536ac495dSmrg * writers to 'assume' Allocator::pointer is a typedef for a normal
26636ac495dSmrg * pointer. This class supports most of the conventions of a true
26736ac495dSmrg * pointer, and can, for instance handle implicit conversion to
26836ac495dSmrg * const and base class pointer types. The only impositions on
26936ac495dSmrg * container writers to support extended pointers are: 1) use the
27036ac495dSmrg * Allocator::pointer typedef appropriately for pointer types. 2)
27136ac495dSmrg * if you need pointer casting, use the __pointer_cast<> functions
27236ac495dSmrg * from ext/cast.h. This allows pointer cast operations to be
27336ac495dSmrg * overloaded as necessary by custom pointers.
27436ac495dSmrg *
27536ac495dSmrg * Note: The const qualifier works with this pointer adapter as
27636ac495dSmrg * follows:
27736ac495dSmrg *
27836ac495dSmrg * _Tp* == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
27936ac495dSmrg * const _Tp* == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
28036ac495dSmrg * _Tp* const == const _Pointer_adapter<_Std_pointer_impl<_Tp> >;
28136ac495dSmrg * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
28236ac495dSmrg */
28336ac495dSmrg template<typename _Storage_policy>
28436ac495dSmrg class _Pointer_adapter : public _Storage_policy
28536ac495dSmrg {
28636ac495dSmrg public:
28736ac495dSmrg typedef typename _Storage_policy::element_type element_type;
28836ac495dSmrg
28936ac495dSmrg // These are needed for iterator_traits
29036ac495dSmrg typedef std::random_access_iterator_tag iterator_category;
29136ac495dSmrg typedef typename _Unqualified_type<element_type>::type value_type;
29236ac495dSmrg typedef std::ptrdiff_t difference_type;
29336ac495dSmrg typedef _Pointer_adapter pointer;
29436ac495dSmrg typedef typename _Reference_type<element_type>::reference reference;
29536ac495dSmrg
29636ac495dSmrg // Reminder: 'const' methods mean that the method is valid when the
29736ac495dSmrg // pointer is immutable, and has nothing to do with whether the
29836ac495dSmrg // 'pointee' is const.
29936ac495dSmrg
30036ac495dSmrg // Default Constructor (Convert from element_type*)
30136ac495dSmrg _Pointer_adapter(element_type* __arg = 0)
30236ac495dSmrg { _Storage_policy::set(__arg); }
30336ac495dSmrg
30436ac495dSmrg // Copy constructor from _Pointer_adapter of same type.
30536ac495dSmrg _Pointer_adapter(const _Pointer_adapter& __arg)
30636ac495dSmrg { _Storage_policy::set(__arg.get()); }
30736ac495dSmrg
30836ac495dSmrg // Convert from _Up* if conversion to element_type* is valid.
30936ac495dSmrg template<typename _Up>
31036ac495dSmrg _Pointer_adapter(_Up* __arg)
31136ac495dSmrg { _Storage_policy::set(__arg); }
31236ac495dSmrg
31336ac495dSmrg // Conversion from another _Pointer_adapter if _Up if static cast is
31436ac495dSmrg // valid.
31536ac495dSmrg template<typename _Up>
31636ac495dSmrg _Pointer_adapter(const _Pointer_adapter<_Up>& __arg)
31736ac495dSmrg { _Storage_policy::set(__arg.get()); }
31836ac495dSmrg
31936ac495dSmrg // Destructor
32036ac495dSmrg ~_Pointer_adapter() { }
32136ac495dSmrg
32236ac495dSmrg // Assignment operator
32336ac495dSmrg _Pointer_adapter&
32436ac495dSmrg operator=(const _Pointer_adapter& __arg)
32536ac495dSmrg {
32636ac495dSmrg _Storage_policy::set(__arg.get());
32736ac495dSmrg return *this;
32836ac495dSmrg }
32936ac495dSmrg
33036ac495dSmrg template<typename _Up>
33136ac495dSmrg _Pointer_adapter&
33236ac495dSmrg operator=(const _Pointer_adapter<_Up>& __arg)
33336ac495dSmrg {
33436ac495dSmrg _Storage_policy::set(__arg.get());
33536ac495dSmrg return *this;
33636ac495dSmrg }
33736ac495dSmrg
33836ac495dSmrg template<typename _Up>
33936ac495dSmrg _Pointer_adapter&
34036ac495dSmrg operator=(_Up* __arg)
34136ac495dSmrg {
34236ac495dSmrg _Storage_policy::set(__arg);
34336ac495dSmrg return *this;
34436ac495dSmrg }
34536ac495dSmrg
34636ac495dSmrg // Operator*, returns element_type&
34736ac495dSmrg inline reference
34836ac495dSmrg operator*() const
34936ac495dSmrg { return *(_Storage_policy::get()); }
35036ac495dSmrg
35136ac495dSmrg // Operator->, returns element_type*
35236ac495dSmrg inline element_type*
35336ac495dSmrg operator->() const
35436ac495dSmrg { return _Storage_policy::get(); }
35536ac495dSmrg
35636ac495dSmrg // Operator[], returns a element_type& to the item at that loc.
35736ac495dSmrg inline reference
35836ac495dSmrg operator[](std::ptrdiff_t __index) const
35936ac495dSmrg { return _Storage_policy::get()[__index]; }
36036ac495dSmrg
36136ac495dSmrg // To allow implicit conversion to "bool", for "if (ptr)..."
362c0a68be4Smrg #if __cplusplus >= 201103L
363c0a68be4Smrg explicit operator bool() const { return _Storage_policy::get() != 0; }
364c0a68be4Smrg #else
36536ac495dSmrg private:
36636ac495dSmrg typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;
36736ac495dSmrg
36836ac495dSmrg public:
36936ac495dSmrg operator __unspecified_bool_type() const
37036ac495dSmrg {
37136ac495dSmrg return _Storage_policy::get() == 0 ? 0 :
37236ac495dSmrg &_Pointer_adapter::operator->;
37336ac495dSmrg }
37436ac495dSmrg
37536ac495dSmrg // ! operator (for: if (!ptr)...)
37636ac495dSmrg inline bool
37736ac495dSmrg operator!() const
37836ac495dSmrg { return (_Storage_policy::get() == 0); }
379c0a68be4Smrg #endif
38036ac495dSmrg
38136ac495dSmrg // Pointer differences
38236ac495dSmrg inline friend std::ptrdiff_t
38336ac495dSmrg operator-(const _Pointer_adapter& __lhs, element_type* __rhs)
38436ac495dSmrg { return (__lhs.get() - __rhs); }
38536ac495dSmrg
38636ac495dSmrg inline friend std::ptrdiff_t
38736ac495dSmrg operator-(element_type* __lhs, const _Pointer_adapter& __rhs)
38836ac495dSmrg { return (__lhs - __rhs.get()); }
38936ac495dSmrg
39036ac495dSmrg template<typename _Up>
39136ac495dSmrg inline friend std::ptrdiff_t
39236ac495dSmrg operator-(const _Pointer_adapter& __lhs, _Up* __rhs)
39336ac495dSmrg { return (__lhs.get() - __rhs); }
39436ac495dSmrg
39536ac495dSmrg template<typename _Up>
39636ac495dSmrg inline friend std::ptrdiff_t
39736ac495dSmrg operator-(_Up* __lhs, const _Pointer_adapter& __rhs)
39836ac495dSmrg { return (__lhs - __rhs.get()); }
39936ac495dSmrg
40036ac495dSmrg template<typename _Up>
40136ac495dSmrg inline std::ptrdiff_t
40236ac495dSmrg operator-(const _Pointer_adapter<_Up>& __rhs) const
40336ac495dSmrg { return (_Storage_policy::get() - __rhs.get()); }
40436ac495dSmrg
40536ac495dSmrg // Pointer math
40636ac495dSmrg // Note: There is a reason for all this overloading based on different
40736ac495dSmrg // integer types. In some libstdc++-v3 test cases, a templated
40836ac495dSmrg // operator+ is declared which can match any types. This operator
40936ac495dSmrg // tends to "steal" the recognition of _Pointer_adapter's own operator+
41036ac495dSmrg // unless the integer type matches perfectly.
41136ac495dSmrg
41236ac495dSmrg #define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \
41336ac495dSmrg inline friend _Pointer_adapter \
41436ac495dSmrg operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
41536ac495dSmrg { return _Pointer_adapter(__lhs.get() + __offset); } \
41636ac495dSmrg \
41736ac495dSmrg inline friend _Pointer_adapter \
41836ac495dSmrg operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \
41936ac495dSmrg { return _Pointer_adapter(__rhs.get() + __offset); } \
42036ac495dSmrg \
42136ac495dSmrg inline friend _Pointer_adapter \
42236ac495dSmrg operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
42336ac495dSmrg { return _Pointer_adapter(__lhs.get() - __offset); } \
42436ac495dSmrg \
42536ac495dSmrg inline _Pointer_adapter& \
42636ac495dSmrg operator+=(INT_TYPE __offset) \
42736ac495dSmrg { \
42836ac495dSmrg _Storage_policy::set(_Storage_policy::get() + __offset); \
42936ac495dSmrg return *this; \
43036ac495dSmrg } \
43136ac495dSmrg \
43236ac495dSmrg inline _Pointer_adapter& \
43336ac495dSmrg operator-=(INT_TYPE __offset) \
43436ac495dSmrg { \
43536ac495dSmrg _Storage_policy::set(_Storage_policy::get() - __offset); \
43636ac495dSmrg return *this; \
43736ac495dSmrg } \
43836ac495dSmrg // END of _CXX_POINTER_ARITH_OPERATOR_SET macro
43936ac495dSmrg
44036ac495dSmrg // Expand into the various pointer arithmetic operators needed.
44136ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(short);
44236ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
44336ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(int);
44436ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
44536ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(long);
44636ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
44736ac495dSmrg #ifdef _GLIBCXX_USE_LONG_LONG
44836ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(long long);
44936ac495dSmrg _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long);
45036ac495dSmrg #endif
45136ac495dSmrg
45236ac495dSmrg // Mathematical Manipulators
45336ac495dSmrg inline _Pointer_adapter&
45436ac495dSmrg operator++()
45536ac495dSmrg {
45636ac495dSmrg _Storage_policy::set(_Storage_policy::get() + 1);
45736ac495dSmrg return *this;
45836ac495dSmrg }
45936ac495dSmrg
46036ac495dSmrg inline _Pointer_adapter
46136ac495dSmrg operator++(int)
46236ac495dSmrg {
46336ac495dSmrg _Pointer_adapter __tmp(*this);
46436ac495dSmrg _Storage_policy::set(_Storage_policy::get() + 1);
46536ac495dSmrg return __tmp;
46636ac495dSmrg }
46736ac495dSmrg
46836ac495dSmrg inline _Pointer_adapter&
46936ac495dSmrg operator--()
47036ac495dSmrg {
47136ac495dSmrg _Storage_policy::set(_Storage_policy::get() - 1);
47236ac495dSmrg return *this;
47336ac495dSmrg }
47436ac495dSmrg
47536ac495dSmrg inline _Pointer_adapter
47636ac495dSmrg operator--(int)
47736ac495dSmrg {
47836ac495dSmrg _Pointer_adapter __tmp(*this);
47936ac495dSmrg _Storage_policy::set(_Storage_policy::get() - 1);
48036ac495dSmrg return __tmp;
48136ac495dSmrg }
48236ac495dSmrg
483*8feb0f0bSmrg #if __cpp_lib_three_way_comparison
484*8feb0f0bSmrg friend std::strong_ordering
485*8feb0f0bSmrg operator<=>(const _Pointer_adapter& __lhs, const _Pointer_adapter& __rhs)
486*8feb0f0bSmrg noexcept
487*8feb0f0bSmrg { return __lhs.get() <=> __rhs.get(); }
488*8feb0f0bSmrg #endif
48936ac495dSmrg }; // class _Pointer_adapter
49036ac495dSmrg
49136ac495dSmrg
49236ac495dSmrg #define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \
49336ac495dSmrg template<typename _Tp1, typename _Tp2> \
49436ac495dSmrg inline bool \
49536ac495dSmrg operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
49636ac495dSmrg { return __lhs.get() OPERATOR __rhs; } \
49736ac495dSmrg \
49836ac495dSmrg template<typename _Tp1, typename _Tp2> \
49936ac495dSmrg inline bool \
50036ac495dSmrg operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
50136ac495dSmrg { return __lhs OPERATOR __rhs.get(); } \
50236ac495dSmrg \
50336ac495dSmrg template<typename _Tp1, typename _Tp2> \
50436ac495dSmrg inline bool \
50536ac495dSmrg operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \
50636ac495dSmrg const _Pointer_adapter<_Tp2>& __rhs) \
50736ac495dSmrg { return __lhs.get() OPERATOR __rhs.get(); } \
50836ac495dSmrg \
50936ac495dSmrg // End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro
51036ac495dSmrg
51136ac495dSmrg // Expand into the various comparison operators needed.
51236ac495dSmrg _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==)
51336ac495dSmrg _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=)
51436ac495dSmrg _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<)
51536ac495dSmrg _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=)
51636ac495dSmrg _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>)
51736ac495dSmrg _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=)
51836ac495dSmrg
51936ac495dSmrg // These are here for expressions like "ptr == 0", "ptr != 0"
52036ac495dSmrg template<typename _Tp>
52136ac495dSmrg inline bool
52236ac495dSmrg operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
52336ac495dSmrg { return __lhs.get() == reinterpret_cast<void*>(__rhs); }
52436ac495dSmrg
52536ac495dSmrg template<typename _Tp>
52636ac495dSmrg inline bool
52736ac495dSmrg operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
52836ac495dSmrg { return __rhs.get() == reinterpret_cast<void*>(__lhs); }
52936ac495dSmrg
53036ac495dSmrg template<typename _Tp>
53136ac495dSmrg inline bool
53236ac495dSmrg operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
53336ac495dSmrg { return __lhs.get() != reinterpret_cast<void*>(__rhs); }
53436ac495dSmrg
53536ac495dSmrg template<typename _Tp>
53636ac495dSmrg inline bool
53736ac495dSmrg operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
53836ac495dSmrg { return __rhs.get() != reinterpret_cast<void*>(__lhs); }
53936ac495dSmrg
54036ac495dSmrg /**
54136ac495dSmrg * Comparison operators for _Pointer_adapter defer to the base class'
54236ac495dSmrg * comparison operators, when possible.
54336ac495dSmrg */
54436ac495dSmrg template<typename _Tp>
54536ac495dSmrg inline bool
54636ac495dSmrg operator==(const _Pointer_adapter<_Tp>& __lhs,
54736ac495dSmrg const _Pointer_adapter<_Tp>& __rhs)
54836ac495dSmrg { return __lhs._Tp::operator==(__rhs); }
54936ac495dSmrg
55036ac495dSmrg template<typename _Tp>
55136ac495dSmrg inline bool
55236ac495dSmrg operator<=(const _Pointer_adapter<_Tp>& __lhs,
55336ac495dSmrg const _Pointer_adapter<_Tp>& __rhs)
55436ac495dSmrg { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); }
55536ac495dSmrg
55636ac495dSmrg template<typename _Tp>
55736ac495dSmrg inline bool
55836ac495dSmrg operator!=(const _Pointer_adapter<_Tp>& __lhs,
55936ac495dSmrg const _Pointer_adapter<_Tp>& __rhs)
56036ac495dSmrg { return !(__lhs._Tp::operator==(__rhs)); }
56136ac495dSmrg
56236ac495dSmrg template<typename _Tp>
56336ac495dSmrg inline bool
56436ac495dSmrg operator>(const _Pointer_adapter<_Tp>& __lhs,
56536ac495dSmrg const _Pointer_adapter<_Tp>& __rhs)
56636ac495dSmrg { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); }
56736ac495dSmrg
56836ac495dSmrg template<typename _Tp>
56936ac495dSmrg inline bool
57036ac495dSmrg operator>=(const _Pointer_adapter<_Tp>& __lhs,
57136ac495dSmrg const _Pointer_adapter<_Tp>& __rhs)
57236ac495dSmrg { return !(__lhs._Tp::operator<(__rhs)); }
57336ac495dSmrg
57436ac495dSmrg template<typename _CharT, typename _Traits, typename _StoreT>
57536ac495dSmrg inline std::basic_ostream<_CharT, _Traits>&
57636ac495dSmrg operator<<(std::basic_ostream<_CharT, _Traits>& __os,
57736ac495dSmrg const _Pointer_adapter<_StoreT>& __p)
57836ac495dSmrg { return (__os << __p.get()); }
57936ac495dSmrg
58036ac495dSmrg _GLIBCXX_END_NAMESPACE_VERSION
58136ac495dSmrg } // namespace
58236ac495dSmrg
58336ac495dSmrg #if __cplusplus >= 201103L
58436ac495dSmrg namespace std _GLIBCXX_VISIBILITY(default)
58536ac495dSmrg {
58636ac495dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
58736ac495dSmrg
58836ac495dSmrg template<typename _Storage_policy>
58936ac495dSmrg struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
59036ac495dSmrg {
59136ac495dSmrg /// The pointer type
59236ac495dSmrg typedef __gnu_cxx::_Pointer_adapter<_Storage_policy> pointer;
59336ac495dSmrg /// The type pointed to
59436ac495dSmrg typedef typename pointer::element_type element_type;
59536ac495dSmrg /// Type used to represent the difference between two pointers
59636ac495dSmrg typedef typename pointer::difference_type difference_type;
59736ac495dSmrg
59836ac495dSmrg template<typename _Up>
59936ac495dSmrg using rebind = typename __gnu_cxx::_Pointer_adapter<
60036ac495dSmrg typename pointer_traits<_Storage_policy>::template rebind<_Up>>;
60136ac495dSmrg
60236ac495dSmrg static pointer pointer_to(typename pointer::reference __r) noexcept
60336ac495dSmrg { return pointer(std::addressof(__r)); }
60436ac495dSmrg };
60536ac495dSmrg
606*8feb0f0bSmrg #if __cpp_lib_concepts
607*8feb0f0bSmrg template<typename _Policy>
608*8feb0f0bSmrg struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>>
609*8feb0f0bSmrg {
610*8feb0f0bSmrg using value_type
611*8feb0f0bSmrg = typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type;
612*8feb0f0bSmrg };
613*8feb0f0bSmrg #endif
61436ac495dSmrg _GLIBCXX_END_NAMESPACE_VERSION
61536ac495dSmrg } // namespace
61636ac495dSmrg #endif
61736ac495dSmrg
61836ac495dSmrg #endif // _POINTER_H
619