138fd1498Szrj // Custom pointer adapter and sample storage policies
238fd1498Szrj
338fd1498Szrj // Copyright (C) 2008-2018 Free Software Foundation, Inc.
438fd1498Szrj //
538fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free
638fd1498Szrj // software; you can redistribute it and/or modify it under the
738fd1498Szrj // terms of the GNU General Public License as published by the
838fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
938fd1498Szrj // any later version.
1038fd1498Szrj
1138fd1498Szrj // This library is distributed in the hope that it will be useful,
1238fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
1338fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1438fd1498Szrj // GNU General Public License for more details.
1538fd1498Szrj
1638fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
1738fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
1838fd1498Szrj // 3.1, as published by the Free Software Foundation.
1938fd1498Szrj
2038fd1498Szrj // You should have received a copy of the GNU General Public License and
2138fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
2238fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2338fd1498Szrj // <http://www.gnu.org/licenses/>.
2438fd1498Szrj
2538fd1498Szrj /**
2638fd1498Szrj * @file ext/pointer.h
2738fd1498Szrj * This file is a GNU extension to the Standard C++ Library.
2838fd1498Szrj *
2938fd1498Szrj * @author Bob Walters
3038fd1498Szrj *
3138fd1498Szrj * Provides reusable _Pointer_adapter for assisting in the development of
3238fd1498Szrj * custom pointer types that can be used with the standard containers via
3338fd1498Szrj * the allocator::pointer and allocator::const_pointer typedefs.
3438fd1498Szrj */
3538fd1498Szrj
3638fd1498Szrj #ifndef _POINTER_H
3738fd1498Szrj #define _POINTER_H 1
3838fd1498Szrj
3938fd1498Szrj #pragma GCC system_header
4038fd1498Szrj
4138fd1498Szrj #include <iosfwd>
4238fd1498Szrj #include <bits/stl_iterator_base_types.h>
4338fd1498Szrj #include <ext/cast.h>
4438fd1498Szrj #include <ext/type_traits.h>
4538fd1498Szrj #if __cplusplus >= 201103L
4638fd1498Szrj # include <bits/move.h>
4738fd1498Szrj # include <bits/ptr_traits.h>
4838fd1498Szrj #endif
4938fd1498Szrj
_GLIBCXX_VISIBILITY(default)5038fd1498Szrj namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
5138fd1498Szrj {
5238fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
5338fd1498Szrj
5438fd1498Szrj /**
5538fd1498Szrj * @brief A storage policy for use with _Pointer_adapter<> which yields a
5638fd1498Szrj * standard pointer.
5738fd1498Szrj *
5838fd1498Szrj * A _Storage_policy is required to provide 4 things:
5938fd1498Szrj * 1) A get() API for returning the stored pointer value.
6038fd1498Szrj * 2) An set() API for storing a pointer value.
6138fd1498Szrj * 3) An element_type typedef to define the type this points to.
6238fd1498Szrj * 4) An operator<() to support pointer comparison.
6338fd1498Szrj * 5) An operator==() to support pointer comparison.
6438fd1498Szrj */
6538fd1498Szrj template<typename _Tp>
6638fd1498Szrj class _Std_pointer_impl
6738fd1498Szrj {
6838fd1498Szrj public:
6938fd1498Szrj // the type this pointer points to.
7038fd1498Szrj typedef _Tp element_type;
7138fd1498Szrj
7238fd1498Szrj // A method to fetch the pointer value as a standard T* value;
7338fd1498Szrj inline _Tp*
7438fd1498Szrj get() const
7538fd1498Szrj { return _M_value; }
7638fd1498Szrj
7738fd1498Szrj // A method to set the pointer value, from a standard T* value;
7838fd1498Szrj inline void
7938fd1498Szrj set(element_type* __arg)
8038fd1498Szrj { _M_value = __arg; }
8138fd1498Szrj
8238fd1498Szrj // Comparison of pointers
8338fd1498Szrj inline bool
8438fd1498Szrj operator<(const _Std_pointer_impl& __rarg) const
8538fd1498Szrj { return (_M_value < __rarg._M_value); }
8638fd1498Szrj
8738fd1498Szrj inline bool
8838fd1498Szrj operator==(const _Std_pointer_impl& __rarg) const
8938fd1498Szrj { return (_M_value == __rarg._M_value); }
9038fd1498Szrj
9138fd1498Szrj private:
9238fd1498Szrj element_type* _M_value;
9338fd1498Szrj };
9438fd1498Szrj
9538fd1498Szrj /**
9638fd1498Szrj * @brief A storage policy for use with _Pointer_adapter<> which stores
9738fd1498Szrj * the pointer's address as an offset value which is relative to
9838fd1498Szrj * its own address.
9938fd1498Szrj *
10038fd1498Szrj * This is intended for pointers within shared memory regions which
10138fd1498Szrj * might be mapped at different addresses by different processes.
10238fd1498Szrj * For null pointers, a value of 1 is used. (0 is legitimate
10338fd1498Szrj * sometimes for nodes in circularly linked lists) This value was
10438fd1498Szrj * chosen as the least likely to generate an incorrect null, As
10538fd1498Szrj * there is no reason why any normal pointer would point 1 byte into
10638fd1498Szrj * its own pointer address.
10738fd1498Szrj */
10838fd1498Szrj template<typename _Tp>
10938fd1498Szrj class _Relative_pointer_impl
11038fd1498Szrj {
11138fd1498Szrj public:
11238fd1498Szrj typedef _Tp element_type;
11338fd1498Szrj
11438fd1498Szrj _Tp*
11538fd1498Szrj get() const
11638fd1498Szrj {
11738fd1498Szrj if (_M_diff == 1)
11838fd1498Szrj return 0;
11938fd1498Szrj else
12038fd1498Szrj return reinterpret_cast<_Tp*>(reinterpret_cast<_UIntPtrType>(this)
12138fd1498Szrj + _M_diff);
12238fd1498Szrj }
12338fd1498Szrj
12438fd1498Szrj void
12538fd1498Szrj set(_Tp* __arg)
12638fd1498Szrj {
12738fd1498Szrj if (!__arg)
12838fd1498Szrj _M_diff = 1;
12938fd1498Szrj else
13038fd1498Szrj _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
13138fd1498Szrj - reinterpret_cast<_UIntPtrType>(this);
13238fd1498Szrj }
13338fd1498Szrj
13438fd1498Szrj // Comparison of pointers
13538fd1498Szrj inline bool
13638fd1498Szrj operator<(const _Relative_pointer_impl& __rarg) const
13738fd1498Szrj { return (reinterpret_cast<_UIntPtrType>(this->get())
13838fd1498Szrj < reinterpret_cast<_UIntPtrType>(__rarg.get())); }
13938fd1498Szrj
14038fd1498Szrj inline bool
14138fd1498Szrj operator==(const _Relative_pointer_impl& __rarg) const
14238fd1498Szrj { return (reinterpret_cast<_UIntPtrType>(this->get())
14338fd1498Szrj == reinterpret_cast<_UIntPtrType>(__rarg.get())); }
14438fd1498Szrj
14538fd1498Szrj private:
14638fd1498Szrj #ifdef _GLIBCXX_USE_LONG_LONG
14738fd1498Szrj typedef __gnu_cxx::__conditional_type<
14838fd1498Szrj (sizeof(unsigned long) >= sizeof(void*)),
14938fd1498Szrj unsigned long, unsigned long long>::__type _UIntPtrType;
15038fd1498Szrj #else
15138fd1498Szrj typedef unsigned long _UIntPtrType;
15238fd1498Szrj #endif
15338fd1498Szrj _UIntPtrType _M_diff;
15438fd1498Szrj };
15538fd1498Szrj
15638fd1498Szrj /**
15738fd1498Szrj * Relative_pointer_impl needs a specialization for const T because of
15838fd1498Szrj * the casting done during pointer arithmetic.
15938fd1498Szrj */
16038fd1498Szrj template<typename _Tp>
16138fd1498Szrj class _Relative_pointer_impl<const _Tp>
16238fd1498Szrj {
16338fd1498Szrj public:
16438fd1498Szrj typedef const _Tp element_type;
16538fd1498Szrj
16638fd1498Szrj const _Tp*
16738fd1498Szrj get() const
16838fd1498Szrj {
16938fd1498Szrj if (_M_diff == 1)
17038fd1498Szrj return 0;
17138fd1498Szrj else
17238fd1498Szrj return reinterpret_cast<const _Tp*>
17338fd1498Szrj (reinterpret_cast<_UIntPtrType>(this) + _M_diff);
17438fd1498Szrj }
17538fd1498Szrj
17638fd1498Szrj void
17738fd1498Szrj set(const _Tp* __arg)
17838fd1498Szrj {
17938fd1498Szrj if (!__arg)
18038fd1498Szrj _M_diff = 1;
18138fd1498Szrj else
18238fd1498Szrj _M_diff = reinterpret_cast<_UIntPtrType>(__arg)
18338fd1498Szrj - reinterpret_cast<_UIntPtrType>(this);
18438fd1498Szrj }
18538fd1498Szrj
18638fd1498Szrj // Comparison of pointers
18738fd1498Szrj inline bool
18838fd1498Szrj operator<(const _Relative_pointer_impl& __rarg) const
18938fd1498Szrj { return (reinterpret_cast<_UIntPtrType>(this->get())
19038fd1498Szrj < reinterpret_cast<_UIntPtrType>(__rarg.get())); }
19138fd1498Szrj
19238fd1498Szrj inline bool
19338fd1498Szrj operator==(const _Relative_pointer_impl& __rarg) const
19438fd1498Szrj { return (reinterpret_cast<_UIntPtrType>(this->get())
19538fd1498Szrj == reinterpret_cast<_UIntPtrType>(__rarg.get())); }
19638fd1498Szrj
19738fd1498Szrj private:
19838fd1498Szrj #ifdef _GLIBCXX_USE_LONG_LONG
19938fd1498Szrj typedef __gnu_cxx::__conditional_type<
20038fd1498Szrj (sizeof(unsigned long) >= sizeof(void*)),
20138fd1498Szrj unsigned long, unsigned long long>::__type _UIntPtrType;
20238fd1498Szrj #else
20338fd1498Szrj typedef unsigned long _UIntPtrType;
20438fd1498Szrj #endif
20538fd1498Szrj _UIntPtrType _M_diff;
20638fd1498Szrj };
20738fd1498Szrj
20838fd1498Szrj /**
20938fd1498Szrj * The specialization on this type helps resolve the problem of
21038fd1498Szrj * reference to void, and eliminates the need to specialize
21138fd1498Szrj * _Pointer_adapter for cases of void*, const void*, and so on.
21238fd1498Szrj */
21338fd1498Szrj struct _Invalid_type { };
21438fd1498Szrj
21538fd1498Szrj template<typename _Tp>
21638fd1498Szrj struct _Reference_type
21738fd1498Szrj { typedef _Tp& reference; };
21838fd1498Szrj
21938fd1498Szrj template<>
22038fd1498Szrj struct _Reference_type<void>
22138fd1498Szrj { typedef _Invalid_type& reference; };
22238fd1498Szrj
22338fd1498Szrj template<>
22438fd1498Szrj struct _Reference_type<const void>
22538fd1498Szrj { typedef const _Invalid_type& reference; };
22638fd1498Szrj
22738fd1498Szrj template<>
22838fd1498Szrj struct _Reference_type<volatile void>
22938fd1498Szrj { typedef volatile _Invalid_type& reference; };
23038fd1498Szrj
23138fd1498Szrj template<>
23238fd1498Szrj struct _Reference_type<volatile const void>
23338fd1498Szrj { typedef const volatile _Invalid_type& reference; };
23438fd1498Szrj
23538fd1498Szrj /**
23638fd1498Szrj * This structure accommodates the way in which
23738fd1498Szrj * std::iterator_traits<> is normally specialized for const T*, so
23838fd1498Szrj * that value_type is still T.
23938fd1498Szrj */
24038fd1498Szrj template<typename _Tp>
24138fd1498Szrj struct _Unqualified_type
24238fd1498Szrj { typedef _Tp type; };
24338fd1498Szrj
24438fd1498Szrj template<typename _Tp>
24538fd1498Szrj struct _Unqualified_type<const _Tp>
24638fd1498Szrj { typedef _Tp type; };
24738fd1498Szrj
24838fd1498Szrj /**
24938fd1498Szrj * The following provides an 'alternative pointer' that works with
25038fd1498Szrj * the containers when specified as the pointer typedef of the
25138fd1498Szrj * allocator.
25238fd1498Szrj *
25338fd1498Szrj * The pointer type used with the containers doesn't have to be this
25438fd1498Szrj * class, but it must support the implicit conversions, pointer
25538fd1498Szrj * arithmetic, comparison operators, etc. that are supported by this
25638fd1498Szrj * class, and avoid raising compile-time ambiguities. Because
25738fd1498Szrj * creating a working pointer can be challenging, this pointer
25838fd1498Szrj * template was designed to wrapper an easier storage policy type,
25938fd1498Szrj * so that it becomes reusable for creating other pointer types.
26038fd1498Szrj *
26138fd1498Szrj * A key point of this class is also that it allows container
26238fd1498Szrj * writers to 'assume' Allocator::pointer is a typedef for a normal
26338fd1498Szrj * pointer. This class supports most of the conventions of a true
26438fd1498Szrj * pointer, and can, for instance handle implicit conversion to
26538fd1498Szrj * const and base class pointer types. The only impositions on
26638fd1498Szrj * container writers to support extended pointers are: 1) use the
26738fd1498Szrj * Allocator::pointer typedef appropriately for pointer types. 2)
26838fd1498Szrj * if you need pointer casting, use the __pointer_cast<> functions
26938fd1498Szrj * from ext/cast.h. This allows pointer cast operations to be
27038fd1498Szrj * overloaded as necessary by custom pointers.
27138fd1498Szrj *
27238fd1498Szrj * Note: The const qualifier works with this pointer adapter as
27338fd1498Szrj * follows:
27438fd1498Szrj *
27538fd1498Szrj * _Tp* == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
27638fd1498Szrj * const _Tp* == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
27738fd1498Szrj * _Tp* const == const _Pointer_adapter<_Std_pointer_impl<_Tp> >;
27838fd1498Szrj * const _Tp* const == const _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
27938fd1498Szrj */
28038fd1498Szrj template<typename _Storage_policy>
28138fd1498Szrj class _Pointer_adapter : public _Storage_policy
28238fd1498Szrj {
28338fd1498Szrj public:
28438fd1498Szrj typedef typename _Storage_policy::element_type element_type;
28538fd1498Szrj
28638fd1498Szrj // These are needed for iterator_traits
28738fd1498Szrj typedef std::random_access_iterator_tag iterator_category;
28838fd1498Szrj typedef typename _Unqualified_type<element_type>::type value_type;
28938fd1498Szrj typedef std::ptrdiff_t difference_type;
29038fd1498Szrj typedef _Pointer_adapter pointer;
29138fd1498Szrj typedef typename _Reference_type<element_type>::reference reference;
29238fd1498Szrj
29338fd1498Szrj // Reminder: 'const' methods mean that the method is valid when the
29438fd1498Szrj // pointer is immutable, and has nothing to do with whether the
29538fd1498Szrj // 'pointee' is const.
29638fd1498Szrj
29738fd1498Szrj // Default Constructor (Convert from element_type*)
29838fd1498Szrj _Pointer_adapter(element_type* __arg = 0)
29938fd1498Szrj { _Storage_policy::set(__arg); }
30038fd1498Szrj
30138fd1498Szrj // Copy constructor from _Pointer_adapter of same type.
30238fd1498Szrj _Pointer_adapter(const _Pointer_adapter& __arg)
30338fd1498Szrj { _Storage_policy::set(__arg.get()); }
30438fd1498Szrj
30538fd1498Szrj // Convert from _Up* if conversion to element_type* is valid.
30638fd1498Szrj template<typename _Up>
30738fd1498Szrj _Pointer_adapter(_Up* __arg)
30838fd1498Szrj { _Storage_policy::set(__arg); }
30938fd1498Szrj
31038fd1498Szrj // Conversion from another _Pointer_adapter if _Up if static cast is
31138fd1498Szrj // valid.
31238fd1498Szrj template<typename _Up>
31338fd1498Szrj _Pointer_adapter(const _Pointer_adapter<_Up>& __arg)
31438fd1498Szrj { _Storage_policy::set(__arg.get()); }
31538fd1498Szrj
31638fd1498Szrj // Destructor
31738fd1498Szrj ~_Pointer_adapter() { }
31838fd1498Szrj
31938fd1498Szrj // Assignment operator
32038fd1498Szrj _Pointer_adapter&
32138fd1498Szrj operator=(const _Pointer_adapter& __arg)
32238fd1498Szrj {
32338fd1498Szrj _Storage_policy::set(__arg.get());
32438fd1498Szrj return *this;
32538fd1498Szrj }
32638fd1498Szrj
32738fd1498Szrj template<typename _Up>
32838fd1498Szrj _Pointer_adapter&
32938fd1498Szrj operator=(const _Pointer_adapter<_Up>& __arg)
33038fd1498Szrj {
33138fd1498Szrj _Storage_policy::set(__arg.get());
33238fd1498Szrj return *this;
33338fd1498Szrj }
33438fd1498Szrj
33538fd1498Szrj template<typename _Up>
33638fd1498Szrj _Pointer_adapter&
33738fd1498Szrj operator=(_Up* __arg)
33838fd1498Szrj {
33938fd1498Szrj _Storage_policy::set(__arg);
34038fd1498Szrj return *this;
34138fd1498Szrj }
34238fd1498Szrj
34338fd1498Szrj // Operator*, returns element_type&
34438fd1498Szrj inline reference
34538fd1498Szrj operator*() const
34638fd1498Szrj { return *(_Storage_policy::get()); }
34738fd1498Szrj
34838fd1498Szrj // Operator->, returns element_type*
34938fd1498Szrj inline element_type*
35038fd1498Szrj operator->() const
35138fd1498Szrj { return _Storage_policy::get(); }
35238fd1498Szrj
35338fd1498Szrj // Operator[], returns a element_type& to the item at that loc.
35438fd1498Szrj inline reference
35538fd1498Szrj operator[](std::ptrdiff_t __index) const
35638fd1498Szrj { return _Storage_policy::get()[__index]; }
35738fd1498Szrj
35838fd1498Szrj // To allow implicit conversion to "bool", for "if (ptr)..."
35938fd1498Szrj private:
36038fd1498Szrj typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;
36138fd1498Szrj
36238fd1498Szrj public:
36338fd1498Szrj operator __unspecified_bool_type() const
36438fd1498Szrj {
36538fd1498Szrj return _Storage_policy::get() == 0 ? 0 :
36638fd1498Szrj &_Pointer_adapter::operator->;
36738fd1498Szrj }
36838fd1498Szrj
36938fd1498Szrj // ! operator (for: if (!ptr)...)
37038fd1498Szrj inline bool
37138fd1498Szrj operator!() const
37238fd1498Szrj { return (_Storage_policy::get() == 0); }
37338fd1498Szrj
37438fd1498Szrj // Pointer differences
37538fd1498Szrj inline friend std::ptrdiff_t
37638fd1498Szrj operator-(const _Pointer_adapter& __lhs, element_type* __rhs)
37738fd1498Szrj { return (__lhs.get() - __rhs); }
37838fd1498Szrj
37938fd1498Szrj inline friend std::ptrdiff_t
38038fd1498Szrj operator-(element_type* __lhs, const _Pointer_adapter& __rhs)
38138fd1498Szrj { return (__lhs - __rhs.get()); }
38238fd1498Szrj
38338fd1498Szrj template<typename _Up>
38438fd1498Szrj inline friend std::ptrdiff_t
38538fd1498Szrj operator-(const _Pointer_adapter& __lhs, _Up* __rhs)
38638fd1498Szrj { return (__lhs.get() - __rhs); }
38738fd1498Szrj
38838fd1498Szrj template<typename _Up>
38938fd1498Szrj inline friend std::ptrdiff_t
39038fd1498Szrj operator-(_Up* __lhs, const _Pointer_adapter& __rhs)
39138fd1498Szrj { return (__lhs - __rhs.get()); }
39238fd1498Szrj
39338fd1498Szrj template<typename _Up>
39438fd1498Szrj inline std::ptrdiff_t
39538fd1498Szrj operator-(const _Pointer_adapter<_Up>& __rhs) const
39638fd1498Szrj { return (_Storage_policy::get() - __rhs.get()); }
39738fd1498Szrj
39838fd1498Szrj // Pointer math
39938fd1498Szrj // Note: There is a reason for all this overloading based on different
40038fd1498Szrj // integer types. In some libstdc++-v3 test cases, a templated
40138fd1498Szrj // operator+ is declared which can match any types. This operator
40238fd1498Szrj // tends to "steal" the recognition of _Pointer_adapter's own operator+
40338fd1498Szrj // unless the integer type matches perfectly.
40438fd1498Szrj
40538fd1498Szrj #define _CXX_POINTER_ARITH_OPERATOR_SET(INT_TYPE) \
40638fd1498Szrj inline friend _Pointer_adapter \
40738fd1498Szrj operator+(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
40838fd1498Szrj { return _Pointer_adapter(__lhs.get() + __offset); } \
40938fd1498Szrj \
41038fd1498Szrj inline friend _Pointer_adapter \
41138fd1498Szrj operator+(INT_TYPE __offset, const _Pointer_adapter& __rhs) \
41238fd1498Szrj { return _Pointer_adapter(__rhs.get() + __offset); } \
41338fd1498Szrj \
41438fd1498Szrj inline friend _Pointer_adapter \
41538fd1498Szrj operator-(const _Pointer_adapter& __lhs, INT_TYPE __offset) \
41638fd1498Szrj { return _Pointer_adapter(__lhs.get() - __offset); } \
41738fd1498Szrj \
41838fd1498Szrj inline _Pointer_adapter& \
41938fd1498Szrj operator+=(INT_TYPE __offset) \
42038fd1498Szrj { \
42138fd1498Szrj _Storage_policy::set(_Storage_policy::get() + __offset); \
42238fd1498Szrj return *this; \
42338fd1498Szrj } \
42438fd1498Szrj \
42538fd1498Szrj inline _Pointer_adapter& \
42638fd1498Szrj operator-=(INT_TYPE __offset) \
42738fd1498Szrj { \
42838fd1498Szrj _Storage_policy::set(_Storage_policy::get() - __offset); \
42938fd1498Szrj return *this; \
43038fd1498Szrj } \
43138fd1498Szrj // END of _CXX_POINTER_ARITH_OPERATOR_SET macro
43238fd1498Szrj
43338fd1498Szrj // Expand into the various pointer arithmetic operators needed.
43438fd1498Szrj _CXX_POINTER_ARITH_OPERATOR_SET(short);
43538fd1498Szrj _CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
43638fd1498Szrj _CXX_POINTER_ARITH_OPERATOR_SET(int);
43738fd1498Szrj _CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
43838fd1498Szrj _CXX_POINTER_ARITH_OPERATOR_SET(long);
43938fd1498Szrj _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
440*58e805e6Szrj #ifdef _GLIBCXX_USE_LONG_LONG
441*58e805e6Szrj _CXX_POINTER_ARITH_OPERATOR_SET(long long);
442*58e805e6Szrj _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long);
443*58e805e6Szrj #endif
44438fd1498Szrj
44538fd1498Szrj // Mathematical Manipulators
44638fd1498Szrj inline _Pointer_adapter&
44738fd1498Szrj operator++()
44838fd1498Szrj {
44938fd1498Szrj _Storage_policy::set(_Storage_policy::get() + 1);
45038fd1498Szrj return *this;
45138fd1498Szrj }
45238fd1498Szrj
45338fd1498Szrj inline _Pointer_adapter
45438fd1498Szrj operator++(int)
45538fd1498Szrj {
45638fd1498Szrj _Pointer_adapter __tmp(*this);
45738fd1498Szrj _Storage_policy::set(_Storage_policy::get() + 1);
45838fd1498Szrj return __tmp;
45938fd1498Szrj }
46038fd1498Szrj
46138fd1498Szrj inline _Pointer_adapter&
46238fd1498Szrj operator--()
46338fd1498Szrj {
46438fd1498Szrj _Storage_policy::set(_Storage_policy::get() - 1);
46538fd1498Szrj return *this;
46638fd1498Szrj }
46738fd1498Szrj
46838fd1498Szrj inline _Pointer_adapter
46938fd1498Szrj operator--(int)
47038fd1498Szrj {
47138fd1498Szrj _Pointer_adapter __tmp(*this);
47238fd1498Szrj _Storage_policy::set(_Storage_policy::get() - 1);
47338fd1498Szrj return __tmp;
47438fd1498Szrj }
47538fd1498Szrj
47638fd1498Szrj }; // class _Pointer_adapter
47738fd1498Szrj
47838fd1498Szrj
47938fd1498Szrj #define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \
48038fd1498Szrj template<typename _Tp1, typename _Tp2> \
48138fd1498Szrj inline bool \
48238fd1498Szrj operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
48338fd1498Szrj { return __lhs.get() OPERATOR __rhs; } \
48438fd1498Szrj \
48538fd1498Szrj template<typename _Tp1, typename _Tp2> \
48638fd1498Szrj inline bool \
48738fd1498Szrj operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
48838fd1498Szrj { return __lhs OPERATOR __rhs.get(); } \
48938fd1498Szrj \
49038fd1498Szrj template<typename _Tp1, typename _Tp2> \
49138fd1498Szrj inline bool \
49238fd1498Szrj operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \
49338fd1498Szrj const _Pointer_adapter<_Tp2>& __rhs) \
49438fd1498Szrj { return __lhs.get() OPERATOR __rhs.get(); } \
49538fd1498Szrj \
49638fd1498Szrj // End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro
49738fd1498Szrj
49838fd1498Szrj // Expand into the various comparison operators needed.
49938fd1498Szrj _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==)
50038fd1498Szrj _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=)
50138fd1498Szrj _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<)
50238fd1498Szrj _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=)
50338fd1498Szrj _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>)
50438fd1498Szrj _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=)
50538fd1498Szrj
50638fd1498Szrj // These are here for expressions like "ptr == 0", "ptr != 0"
50738fd1498Szrj template<typename _Tp>
50838fd1498Szrj inline bool
50938fd1498Szrj operator==(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
51038fd1498Szrj { return __lhs.get() == reinterpret_cast<void*>(__rhs); }
51138fd1498Szrj
51238fd1498Szrj template<typename _Tp>
51338fd1498Szrj inline bool
51438fd1498Szrj operator==(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
51538fd1498Szrj { return __rhs.get() == reinterpret_cast<void*>(__lhs); }
51638fd1498Szrj
51738fd1498Szrj template<typename _Tp>
51838fd1498Szrj inline bool
51938fd1498Szrj operator!=(const _Pointer_adapter<_Tp>& __lhs, int __rhs)
52038fd1498Szrj { return __lhs.get() != reinterpret_cast<void*>(__rhs); }
52138fd1498Szrj
52238fd1498Szrj template<typename _Tp>
52338fd1498Szrj inline bool
52438fd1498Szrj operator!=(int __lhs, const _Pointer_adapter<_Tp>& __rhs)
52538fd1498Szrj { return __rhs.get() != reinterpret_cast<void*>(__lhs); }
52638fd1498Szrj
52738fd1498Szrj /**
52838fd1498Szrj * Comparison operators for _Pointer_adapter defer to the base class'
52938fd1498Szrj * comparison operators, when possible.
53038fd1498Szrj */
53138fd1498Szrj template<typename _Tp>
53238fd1498Szrj inline bool
53338fd1498Szrj operator==(const _Pointer_adapter<_Tp>& __lhs,
53438fd1498Szrj const _Pointer_adapter<_Tp>& __rhs)
53538fd1498Szrj { return __lhs._Tp::operator==(__rhs); }
53638fd1498Szrj
53738fd1498Szrj template<typename _Tp>
53838fd1498Szrj inline bool
53938fd1498Szrj operator<=(const _Pointer_adapter<_Tp>& __lhs,
54038fd1498Szrj const _Pointer_adapter<_Tp>& __rhs)
54138fd1498Szrj { return __lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs); }
54238fd1498Szrj
54338fd1498Szrj template<typename _Tp>
54438fd1498Szrj inline bool
54538fd1498Szrj operator!=(const _Pointer_adapter<_Tp>& __lhs,
54638fd1498Szrj const _Pointer_adapter<_Tp>& __rhs)
54738fd1498Szrj { return !(__lhs._Tp::operator==(__rhs)); }
54838fd1498Szrj
54938fd1498Szrj template<typename _Tp>
55038fd1498Szrj inline bool
55138fd1498Szrj operator>(const _Pointer_adapter<_Tp>& __lhs,
55238fd1498Szrj const _Pointer_adapter<_Tp>& __rhs)
55338fd1498Szrj { return !(__lhs._Tp::operator<(__rhs) || __lhs._Tp::operator==(__rhs)); }
55438fd1498Szrj
55538fd1498Szrj template<typename _Tp>
55638fd1498Szrj inline bool
55738fd1498Szrj operator>=(const _Pointer_adapter<_Tp>& __lhs,
55838fd1498Szrj const _Pointer_adapter<_Tp>& __rhs)
55938fd1498Szrj { return !(__lhs._Tp::operator<(__rhs)); }
56038fd1498Szrj
56138fd1498Szrj template<typename _CharT, typename _Traits, typename _StoreT>
56238fd1498Szrj inline std::basic_ostream<_CharT, _Traits>&
56338fd1498Szrj operator<<(std::basic_ostream<_CharT, _Traits>& __os,
56438fd1498Szrj const _Pointer_adapter<_StoreT>& __p)
56538fd1498Szrj { return (__os << __p.get()); }
56638fd1498Szrj
56738fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
56838fd1498Szrj } // namespace
56938fd1498Szrj
57038fd1498Szrj #if __cplusplus >= 201103L
57138fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
57238fd1498Szrj {
57338fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
57438fd1498Szrj
57538fd1498Szrj template<typename _Storage_policy>
57638fd1498Szrj struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
57738fd1498Szrj {
57838fd1498Szrj /// The pointer type
57938fd1498Szrj typedef __gnu_cxx::_Pointer_adapter<_Storage_policy> pointer;
58038fd1498Szrj /// The type pointed to
58138fd1498Szrj typedef typename pointer::element_type element_type;
58238fd1498Szrj /// Type used to represent the difference between two pointers
58338fd1498Szrj typedef typename pointer::difference_type difference_type;
58438fd1498Szrj
58538fd1498Szrj template<typename _Up>
58638fd1498Szrj using rebind = typename __gnu_cxx::_Pointer_adapter<
58738fd1498Szrj typename pointer_traits<_Storage_policy>::template rebind<_Up>>;
58838fd1498Szrj
58938fd1498Szrj static pointer pointer_to(typename pointer::reference __r) noexcept
59038fd1498Szrj { return pointer(std::addressof(__r)); }
59138fd1498Szrj };
59238fd1498Szrj
59338fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
59438fd1498Szrj } // namespace
59538fd1498Szrj #endif
59638fd1498Szrj
59738fd1498Szrj #endif // _POINTER_H
598