Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/experimental/propagate_const
1 // <experimental/propagate_const> -*- C++ -*- 2 3 // Copyright (C) 2015-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 /** @file experimental/propagate_const 26 * This is a TS C++ Library header. 27 * @ingroup libfund-ts 28 */ 29 30 #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 31 #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1 32 33 #ifdef _GLIBCXX_SYSHDR 34 #pragma GCC system_header 35 #endif 36 37 #include <bits/requires_hosted.h> // experimental is currently omitted 38 39 #if __cplusplus >= 201402L 40 41 #include <type_traits> 42 #include <bits/functional_hash.h> 43 #include <bits/move.h> 44 #include <bits/stl_function.h> 45 #include <experimental/bits/lfts_config.h> 46 47 namespace std _GLIBCXX_VISIBILITY(default) 48 { 49 _GLIBCXX_BEGIN_NAMESPACE_VERSION 50 51 namespace experimental 52 { 53 inline namespace fundamentals_v2 54 { 55 template<typename _Tp> 56 using __propagate_const_elem_type 57 = remove_reference_t<decltype(*std::declval<_Tp&>())>; 58 59 template<typename _Tp, 60 typename _Elem = __propagate_const_elem_type<_Tp>, 61 bool = is_convertible<const _Tp, const _Elem*>::value> 62 struct __propagate_const_conversion_c 63 { }; 64 65 template<typename _Tp, typename _Elem> 66 struct __propagate_const_conversion_c<_Tp, _Elem, true> 67 { 68 constexpr operator const _Elem*() const; 69 }; 70 71 template<typename _Tp, 72 typename _Elem = __propagate_const_elem_type<_Tp>, 73 bool = is_convertible<_Tp, _Elem*>::value> 74 struct __propagate_const_conversion_nc 75 { }; 76 77 template<typename _Tp, typename _Elem> 78 struct __propagate_const_conversion_nc<_Tp, _Elem, true> 79 { 80 constexpr operator _Elem*(); 81 }; 82 83 // Base class of propagate_const<T> when T is a class type. 84 template <typename _Tp> 85 struct __propagate_const_conversions 86 : __propagate_const_conversion_c<_Tp>, __propagate_const_conversion_nc<_Tp> 87 { }; 88 89 // Base class of propagate_const<T> when T is a pointer type. 90 template<typename _Tp> 91 struct __propagate_const_conversions<_Tp*> 92 { 93 constexpr operator const _Tp*() const noexcept; 94 constexpr operator _Tp*() noexcept; 95 }; 96 97 /** 98 * @defgroup propagate_const Const-propagating wrapper 99 * @ingroup libfund-ts 100 * 101 * A const-propagating wrapper that propagates const to pointer-like members, 102 * as described in n4388 "A Proposal to Add a Const-Propagating Wrapper 103 * to the Standard Library". 104 * 105 * @{ 106 */ 107 108 /// Const-propagating wrapper. 109 template <typename _Tp> 110 class propagate_const : public __propagate_const_conversions<_Tp> 111 { 112 public: 113 using element_type = __propagate_const_elem_type<_Tp>; 114 115 private: 116 template <typename _Up> 117 struct __is_propagate_const : false_type 118 { }; 119 120 template <typename _Up> 121 struct __is_propagate_const<propagate_const<_Up>> : true_type 122 { }; 123 124 template <typename _Up> 125 friend constexpr const _Up& 126 get_underlying(const propagate_const<_Up>& __pt) noexcept; 127 template <typename _Up> 128 friend constexpr _Up& 129 get_underlying(propagate_const<_Up>& __pt) noexcept; 130 131 template <typename _Up> 132 static constexpr element_type* 133 __to_raw_pointer(_Up* __u) 134 { return __u; } 135 136 template <typename _Up> 137 static constexpr element_type* 138 __to_raw_pointer(_Up& __u) 139 { return __u.get(); } 140 141 template <typename _Up> 142 static constexpr const element_type* 143 __to_raw_pointer(const _Up* __u) 144 { return __u; } 145 146 template <typename _Up> 147 static constexpr const element_type* 148 __to_raw_pointer(const _Up& __u) 149 { return __u.get(); } 150 151 public: 152 static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>, 153 __not_<is_array<_Tp>>, 154 __or_<is_class<_Tp>, is_pointer<_Tp>>>::value, 155 "propagate_const requires a class or a pointer to an" 156 " object type"); 157 158 // [propagate_const.ctor], constructors 159 constexpr propagate_const() = default; 160 propagate_const(const propagate_const& __p) = delete; 161 constexpr propagate_const(propagate_const&& __p) = default; 162 163 template <typename _Up, typename 164 enable_if<__and_<is_constructible<_Tp, _Up&&>, 165 is_convertible<_Up&&, _Tp>>::value, bool 166 >::type=true> 167 constexpr propagate_const(propagate_const<_Up>&& __pu) 168 : _M_t(std::move(get_underlying(__pu))) 169 {} 170 171 template <typename _Up, typename 172 enable_if<__and_<is_constructible<_Tp, _Up&&>, 173 __not_<is_convertible<_Up&&, _Tp>>>::value, 174 bool>::type=false> 175 constexpr explicit propagate_const(propagate_const<_Up>&& __pu) 176 : _M_t(std::move(get_underlying(__pu))) 177 {} 178 179 template <typename _Up, typename 180 enable_if<__and_<is_constructible<_Tp, _Up&&>, 181 is_convertible<_Up&&, _Tp>, 182 __not_<__is_propagate_const< 183 typename decay<_Up>::type>> 184 >::value, bool>::type=true> 185 constexpr propagate_const(_Up&& __u) 186 : _M_t(std::forward<_Up>(__u)) 187 {} 188 189 template <typename _Up, typename 190 enable_if<__and_<is_constructible<_Tp, _Up&&>, 191 __not_<is_convertible<_Up&&, _Tp>>, 192 __not_<__is_propagate_const< 193 typename decay<_Up>::type>> 194 >::value, bool>::type=false> 195 constexpr explicit propagate_const(_Up&& __u) 196 : _M_t(std::forward<_Up>(__u)) 197 {} 198 199 // [propagate_const.assignment], assignment 200 propagate_const& operator=(const propagate_const& __p) = delete; 201 constexpr propagate_const& operator=(propagate_const&& __p) = default; 202 203 template <typename _Up, typename = 204 typename enable_if<is_convertible<_Up&&, _Tp>::value>::type> 205 constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) 206 { 207 _M_t = std::move(get_underlying(__pu)); 208 return *this; 209 } 210 211 template <typename _Up, typename = 212 typename enable_if<__and_<is_convertible<_Up&&, _Tp>, 213 __not_<__is_propagate_const< 214 typename decay<_Up>::type>> 215 >::value>::type> 216 constexpr propagate_const& operator=(_Up&& __u) 217 { 218 _M_t = std::forward<_Up>(__u); 219 return *this; 220 } 221 222 // [propagate_const.const_observers], const observers 223 explicit constexpr operator bool() const 224 { 225 return bool(_M_t); 226 } 227 228 constexpr const element_type* operator->() const 229 { 230 return get(); 231 } 232 233 constexpr const element_type& operator*() const 234 { 235 return *get(); 236 } 237 238 constexpr const element_type* get() const 239 { 240 return __to_raw_pointer(_M_t); 241 } 242 243 // [propagate_const.non_const_observers], non-const observers 244 constexpr element_type* operator->() 245 { 246 return get(); 247 } 248 249 constexpr element_type& operator*() 250 { 251 return *get(); 252 } 253 254 constexpr element_type* get() 255 { 256 return __to_raw_pointer(_M_t); 257 } 258 259 // [propagate_const.modifiers], modifiers 260 constexpr void 261 swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value) 262 { 263 using std::swap; 264 swap(_M_t, get_underlying(__pt)); 265 } 266 267 private: 268 _Tp _M_t; 269 }; 270 271 // [propagate_const.relational], relational operators 272 template <typename _Tp> 273 constexpr bool 274 operator==(const propagate_const<_Tp>& __pt, nullptr_t) 275 { 276 return get_underlying(__pt) == nullptr; 277 } 278 279 template <typename _Tp> 280 constexpr bool 281 operator==(nullptr_t, const propagate_const<_Tp>& __pu) 282 { 283 return nullptr == get_underlying(__pu); 284 } 285 286 template <typename _Tp> 287 constexpr bool 288 operator!=(const propagate_const<_Tp>& __pt, nullptr_t) 289 { 290 return get_underlying(__pt) != nullptr; 291 } 292 293 template <typename _Tp> 294 constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu) 295 { 296 return nullptr != get_underlying(__pu); 297 } 298 299 template <typename _Tp, typename _Up> 300 constexpr bool 301 operator==(const propagate_const<_Tp>& __pt, 302 const propagate_const<_Up>& __pu) 303 { 304 return get_underlying(__pt) == get_underlying(__pu); 305 } 306 307 template <typename _Tp, typename _Up> 308 constexpr bool 309 operator!=(const propagate_const<_Tp>& __pt, 310 const propagate_const<_Up>& __pu) 311 { 312 return get_underlying(__pt) != get_underlying(__pu); 313 } 314 315 template <typename _Tp, typename _Up> 316 constexpr bool 317 operator<(const propagate_const<_Tp>& __pt, 318 const propagate_const<_Up>& __pu) 319 { 320 return get_underlying(__pt) < get_underlying(__pu); 321 } 322 323 template <typename _Tp, typename _Up> 324 constexpr bool 325 operator>(const propagate_const<_Tp>& __pt, 326 const propagate_const<_Up>& __pu) 327 { 328 return get_underlying(__pt) > get_underlying(__pu); 329 } 330 331 template <typename _Tp, typename _Up> 332 constexpr bool 333 operator<=(const propagate_const<_Tp>& __pt, 334 const propagate_const<_Up>& __pu) 335 { 336 return get_underlying(__pt) <= get_underlying(__pu); 337 } 338 339 template <typename _Tp, typename _Up> 340 constexpr bool 341 operator>=(const propagate_const<_Tp>& __pt, 342 const propagate_const<_Up>& __pu) 343 { 344 return get_underlying(__pt) >= get_underlying(__pu); 345 } 346 347 template <typename _Tp, typename _Up> 348 constexpr bool 349 operator==(const propagate_const<_Tp>& __pt, const _Up& __u) 350 { 351 return get_underlying(__pt) == __u; 352 } 353 354 template <typename _Tp, typename _Up> 355 constexpr bool 356 operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) 357 { 358 return get_underlying(__pt) != __u; 359 } 360 361 template <typename _Tp, typename _Up> 362 constexpr bool 363 operator<(const propagate_const<_Tp>& __pt, const _Up& __u) 364 { 365 return get_underlying(__pt) < __u; 366 } 367 368 template <typename _Tp, typename _Up> 369 constexpr bool 370 operator>(const propagate_const<_Tp>& __pt, const _Up& __u) 371 { 372 return get_underlying(__pt) > __u; 373 } 374 375 template <typename _Tp, typename _Up> 376 constexpr bool 377 operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) 378 { 379 return get_underlying(__pt) <= __u; 380 } 381 382 template <typename _Tp, typename _Up> 383 constexpr bool 384 operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) 385 { 386 return get_underlying(__pt) >= __u; 387 } 388 389 template <typename _Tp, typename _Up> 390 constexpr bool 391 operator==(const _Tp& __t, const propagate_const<_Up>& __pu) 392 { 393 return __t == get_underlying(__pu); 394 } 395 396 template <typename _Tp, typename _Up> 397 constexpr bool 398 operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) 399 { 400 return __t != get_underlying(__pu); 401 } 402 403 template <typename _Tp, typename _Up> 404 constexpr bool 405 operator<(const _Tp& __t, const propagate_const<_Up>& __pu) 406 { 407 return __t < get_underlying(__pu); 408 } 409 410 template <typename _Tp, typename _Up> 411 constexpr bool 412 operator>(const _Tp& __t, const propagate_const<_Up>& __pu) 413 { 414 return __t > get_underlying(__pu); 415 } 416 417 template <typename _Tp, typename _Up> 418 constexpr bool 419 operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) 420 { 421 return __t <= get_underlying(__pu); 422 } 423 424 template <typename _Tp, typename _Up> 425 constexpr bool 426 operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) 427 { 428 return __t >= get_underlying(__pu); 429 } 430 431 // [propagate_const.algorithms], specialized algorithms 432 // _GLIBCXX_RESOLVE_LIB_DEFECTS 433 // 3413. propagate_const's swap [...] needs to be constrained and use a trait 434 template <typename _Tp> 435 constexpr enable_if_t<__is_swappable<_Tp>::value, void> 436 swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2) 437 noexcept(__is_nothrow_swappable<_Tp>::value) 438 { 439 __pt.swap(__pt2); 440 } 441 442 // [propagate_const.underlying], underlying pointer access 443 template <typename _Tp> 444 constexpr const _Tp& 445 get_underlying(const propagate_const<_Tp>& __pt) noexcept 446 { 447 return __pt._M_t; 448 } 449 450 template <typename _Tp> 451 constexpr _Tp& 452 get_underlying(propagate_const<_Tp>& __pt) noexcept 453 { 454 return __pt._M_t; 455 } 456 457 template<typename _Tp> 458 constexpr 459 __propagate_const_conversions<_Tp*>::operator const _Tp*() const noexcept 460 { return static_cast<const propagate_const<_Tp*>*>(this)->get(); } 461 462 template<typename _Tp> 463 constexpr 464 __propagate_const_conversions<_Tp*>::operator _Tp*() noexcept 465 { return static_cast<propagate_const<_Tp*>*>(this)->get(); } 466 467 template<typename _Tp, typename _Elem> 468 constexpr 469 __propagate_const_conversion_c<_Tp, _Elem, true>:: 470 operator const _Elem*() const 471 { return static_cast<const propagate_const<_Tp>*>(this)->get(); } 472 473 template<typename _Tp, typename _Elem> 474 constexpr 475 __propagate_const_conversion_nc<_Tp, _Elem, true>:: 476 operator _Elem*() 477 { return static_cast<propagate_const<_Tp>*>(this)->get(); } 478 479 /// @} group propagate_const 480 } // namespace fundamentals_v2 481 } // namespace experimental 482 483 // [propagate_const.hash], hash support 484 template <typename _Tp> 485 struct hash<experimental::propagate_const<_Tp>> 486 { 487 using result_type = size_t; 488 using argument_type = experimental::propagate_const<_Tp>; 489 490 size_t 491 operator()(const experimental::propagate_const<_Tp>& __t) const 492 noexcept(noexcept(hash<_Tp>{}(get_underlying(__t)))) 493 { 494 return hash<_Tp>{}(get_underlying(__t)); 495 } 496 }; 497 498 // [propagate_const.comparison_function_objects], comparison function objects 499 template <typename _Tp> 500 struct equal_to<experimental::propagate_const<_Tp>> 501 { 502 constexpr bool 503 operator()(const experimental::propagate_const<_Tp>& __x, 504 const experimental::propagate_const<_Tp>& __y) const 505 { 506 return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); 507 } 508 509 typedef experimental::propagate_const<_Tp> first_argument_type; 510 typedef experimental::propagate_const<_Tp> second_argument_type; 511 typedef bool result_type; 512 }; 513 514 template <typename _Tp> 515 struct not_equal_to<experimental::propagate_const<_Tp>> 516 { 517 constexpr bool 518 operator()(const experimental::propagate_const<_Tp>& __x, 519 const experimental::propagate_const<_Tp>& __y) const 520 { 521 return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); 522 } 523 524 typedef experimental::propagate_const<_Tp> first_argument_type; 525 typedef experimental::propagate_const<_Tp> second_argument_type; 526 typedef bool result_type; 527 }; 528 529 template <typename _Tp> 530 struct less<experimental::propagate_const<_Tp>> 531 { 532 constexpr bool 533 operator()(const experimental::propagate_const<_Tp>& __x, 534 const experimental::propagate_const<_Tp>& __y) const 535 { 536 return less<_Tp>{}(get_underlying(__x), get_underlying(__y)); 537 } 538 539 typedef experimental::propagate_const<_Tp> first_argument_type; 540 typedef experimental::propagate_const<_Tp> second_argument_type; 541 typedef bool result_type; 542 }; 543 544 template <typename _Tp> 545 struct greater<experimental::propagate_const<_Tp>> 546 { 547 constexpr bool 548 operator()(const experimental::propagate_const<_Tp>& __x, 549 const experimental::propagate_const<_Tp>& __y) const 550 { 551 return greater<_Tp>{}(get_underlying(__x), get_underlying(__y)); 552 } 553 554 typedef experimental::propagate_const<_Tp> first_argument_type; 555 typedef experimental::propagate_const<_Tp> second_argument_type; 556 typedef bool result_type; 557 }; 558 559 template <typename _Tp> 560 struct less_equal<experimental::propagate_const<_Tp>> 561 { 562 constexpr bool 563 operator()(const experimental::propagate_const<_Tp>& __x, 564 const experimental::propagate_const<_Tp>& __y) const 565 { 566 return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); 567 } 568 569 typedef experimental::propagate_const<_Tp> first_argument_type; 570 typedef experimental::propagate_const<_Tp> second_argument_type; 571 typedef bool result_type; 572 }; 573 574 template <typename _Tp> 575 struct greater_equal<experimental::propagate_const<_Tp>> 576 { 577 constexpr bool 578 operator()(const experimental::propagate_const<_Tp>& __x, 579 const experimental::propagate_const<_Tp>& __y) const 580 { 581 return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); 582 } 583 584 typedef experimental::propagate_const<_Tp> first_argument_type; 585 typedef experimental::propagate_const<_Tp> second_argument_type; 586 typedef bool result_type; 587 }; 588 589 _GLIBCXX_END_NAMESPACE_VERSION 590 } // namespace std 591 592 #endif // C++14 593 594 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST