xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/ext/pointer.h (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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