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