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