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