1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST 11#define _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST 12 13/* 14 propagate_const synopsis 15 16 namespace std { namespace experimental { inline namespace fundamentals_v2 { 17 18 // [propagate_const] 19 template <class T> class propagate_const; 20 21 // [propagate_const.underlying], underlying pointer access 22 constexpr const _Tp& get_underlying(const propagate_const<T>& pt) noexcept; 23 constexpr T& get_underlying(propagate_const<T>& pt) noexcept; 24 25 // [propagate_const.relational], relational operators 26 template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t); 27 template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu); 28 template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t); 29 template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu); 30 template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<_Up>& pu); 31 template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<_Up>& pu); 32 template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<_Up>& pu); 33 template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<_Up>& pu); 34 template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<_Up>& pu); 35 template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<_Up>& pu); 36 template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const _Up& u); 37 template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const _Up& u); 38 template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const _Up& u); 39 template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const _Up& u); 40 template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const _Up& u); 41 template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const _Up& u); 42 template <class T, class U> constexpr bool operator==(const _Tp& t, const propagate_const<_Up>& pu); 43 template <class T, class U> constexpr bool operator!=(const _Tp& t, const propagate_const<_Up>& pu); 44 template <class T, class U> constexpr bool operator<(const _Tp& t, const propagate_const<_Up>& pu); 45 template <class T, class U> constexpr bool operator>(const _Tp& t, const propagate_const<_Up>& pu); 46 template <class T, class U> constexpr bool operator<=(const _Tp& t, const propagate_const<_Up>& pu); 47 template <class T, class U> constexpr bool operator>=(const _Tp& t, const propagate_const<_Up>& pu); 48 49 // [propagate_const.algorithms], specialized algorithms 50 template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below); 51 52 template <class T> 53 class propagate_const 54 { 55 56 public: 57 typedef remove_reference_t<decltype(*declval<T&>())> element_type; 58 59 // [propagate_const.ctor], constructors 60 constexpr propagate_const() = default; 61 propagate_const(const propagate_const& p) = delete; 62 constexpr propagate_const(propagate_const&& p) = default; 63 template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below 64 template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below 65 66 // [propagate_const.assignment], assignment 67 propagate_const& operator=(const propagate_const& p) = delete; 68 constexpr propagate_const& operator=(propagate_const&& p) = default; 69 template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu); 70 template <class U> constexpr propagate_const& operator=(U&& u); // see below 71 72 // [propagate_const.const_observers], const observers 73 explicit constexpr operator bool() const; 74 constexpr const element_type* operator->() const; 75 constexpr operator const element_type*() const; // Not always defined 76 constexpr const element_type& operator*() const; 77 constexpr const element_type* get() const; 78 79 // [propagate_const.non_const_observers], non-const observers 80 constexpr element_type* operator->(); 81 constexpr operator element_type*(); // Not always defined 82 constexpr element_type& operator*(); 83 constexpr element_type* get(); 84 85 // [propagate_const.modifiers], modifiers 86 constexpr void swap(propagate_const& pt) noexcept(see below) 87 88 private: 89 T t_; // exposition only 90 }; 91 92 } // namespace fundamentals_v2 93 } // namespace experimental 94 95 // [propagate_const.hash], hash support 96 template <class T> struct hash<experimental::propagate_const<T>>; 97 98 // [propagate_const.comparison_function_objects], comparison function objects 99 template <class T> struct equal_to<experimental::propagate_const<T>>; 100 template <class T> struct not_equal_to<experimental::propagate_const<T>>; 101 template <class T> struct less<experimental::propagate_const<T>>; 102 template <class T> struct greater<experimental::propagate_const<T>>; 103 template <class T> struct less_equal<experimental::propagate_const<T>>; 104 template <class T> struct greater_equal<experimental::propagate_const<T>>; 105 106} // namespace std 107 108*/ 109 110#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) 111# include <__cxx03/experimental/propagate_const> 112#else 113# include <__config> 114# include <__cstddef/nullptr_t.h> 115# include <__cstddef/size_t.h> 116# include <__functional/operations.h> 117# include <__fwd/functional.h> 118# include <__type_traits/conditional.h> 119# include <__type_traits/decay.h> 120# include <__type_traits/enable_if.h> 121# include <__type_traits/is_array.h> 122# include <__type_traits/is_constructible.h> 123# include <__type_traits/is_convertible.h> 124# include <__type_traits/is_function.h> 125# include <__type_traits/is_pointer.h> 126# include <__type_traits/is_reference.h> 127# include <__type_traits/is_same.h> 128# include <__type_traits/is_swappable.h> 129# include <__type_traits/remove_cv.h> 130# include <__type_traits/remove_pointer.h> 131# include <__type_traits/remove_reference.h> 132# include <__utility/declval.h> 133# include <__utility/forward.h> 134# include <__utility/move.h> 135# include <__utility/swap.h> 136# include <version> 137 138# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 139# pragma GCC system_header 140# endif 141 142_LIBCPP_PUSH_MACROS 143# include <__undef_macros> 144 145# if _LIBCPP_STD_VER >= 14 146 147_LIBCPP_BEGIN_NAMESPACE_LFTS_V2 148 149template <class _Tp> 150class propagate_const; 151 152template <class _Up> 153inline _LIBCPP_HIDE_FROM_ABI constexpr const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT; 154 155template <class _Up> 156inline _LIBCPP_HIDE_FROM_ABI constexpr _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT; 157 158template <class _Tp> 159class propagate_const { 160public: 161 typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type; 162 163 static_assert(!is_array<_Tp>::value, "Instantiation of propagate_const with an array type is ill-formed."); 164 static_assert(!is_reference<_Tp>::value, "Instantiation of propagate_const with a reference type is ill-formed."); 165 static_assert(!(is_pointer<_Tp>::value && is_function<__remove_pointer_t<_Tp> >::value), 166 "Instantiation of propagate_const with a function-pointer type is ill-formed."); 167 static_assert(!(is_pointer<_Tp>::value && is_same<__remove_cv_t<__remove_pointer_t<_Tp> >, void>::value), 168 "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed."); 169 170private: 171 template <class _Up> 172 static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up* __u) { 173 return __u; 174 } 175 176 template <class _Up> 177 static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up& __u) { 178 return __get_pointer(__u.get()); 179 } 180 181 template <class _Up> 182 static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up* __u) { 183 return __u; 184 } 185 186 template <class _Up> 187 static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up& __u) { 188 return __get_pointer(__u.get()); 189 } 190 191 template <class _Up> 192 struct __is_propagate_const : false_type {}; 193 194 template <class _Up> 195 struct __is_propagate_const<propagate_const<_Up>> : true_type {}; 196 197 _Tp __t_; 198 199public: 200 template <class _Up> 201 friend constexpr const _Up& experimental::fundamentals_v2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT; 202 template <class _Up> 203 friend constexpr _Up& experimental::fundamentals_v2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT; 204 205 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const() = default; 206 207 propagate_const(const propagate_const&) = delete; 208 209 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const&&) = default; 210 211 template <class _Up, 212 enable_if_t<!is_convertible<_Up, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = true> 213 explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu) 214 : __t_(std::move(experimental::get_underlying(__pu))) {} 215 216 template <class _Up, 217 enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = false> 218 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu) 219 : __t_(std::move(experimental::get_underlying(__pu))) {} 220 221 template <class _Up, 222 enable_if_t<!is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value && 223 !__is_propagate_const<decay_t<_Up>>::value, 224 bool> = true> 225 explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {} 226 227 template <class _Up, 228 enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value && 229 !__is_propagate_const<decay_t<_Up>>::value, 230 bool> = false> 231 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {} 232 233 propagate_const& operator=(const propagate_const&) = delete; 234 235 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const&&) = default; 236 237 template <class _Up> 238 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) { 239 __t_ = std::move(experimental::get_underlying(__pu)); 240 return *this; 241 } 242 243 template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>> 244 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(_Up&& __u) { 245 __t_ = std::forward<_Up>(__u); 246 return *this; 247 } 248 249 _LIBCPP_HIDE_FROM_ABI constexpr const element_type* get() const { return __get_pointer(__t_); } 250 251 _LIBCPP_HIDE_FROM_ABI constexpr element_type* get() { return __get_pointer(__t_); } 252 253 _LIBCPP_HIDE_FROM_ABI explicit constexpr operator bool() const { return get() != nullptr; } 254 255 _LIBCPP_HIDE_FROM_ABI constexpr const element_type* operator->() const { return get(); } 256 257 template <class _Dummy = _Tp, class _Up = enable_if_t<is_convertible< const _Dummy, const element_type*>::value>> 258 _LIBCPP_HIDE_FROM_ABI constexpr operator const element_type*() const { 259 return get(); 260 } 261 262 _LIBCPP_HIDE_FROM_ABI constexpr const element_type& operator*() const { return *get(); } 263 264 _LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() { return get(); } 265 266 template <class _Dummy = _Tp, class _Up = enable_if_t< is_convertible<_Dummy, element_type*>::value>> 267 _LIBCPP_HIDE_FROM_ABI constexpr operator element_type*() { 268 return get(); 269 } 270 271 _LIBCPP_HIDE_FROM_ABI constexpr element_type& operator*() { return *get(); } 272 273 _LIBCPP_HIDE_FROM_ABI constexpr void swap(propagate_const& __pt) noexcept(__is_nothrow_swappable_v<_Tp>) { 274 using std::swap; 275 swap(__t_, __pt.__t_); 276 } 277}; 278 279template <class _Tp> 280_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, nullptr_t) { 281 return experimental::get_underlying(__pt) == nullptr; 282} 283 284template <class _Tp> 285_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullptr_t, const propagate_const<_Tp>& __pt) { 286 return nullptr == experimental::get_underlying(__pt); 287} 288 289template <class _Tp> 290_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t) { 291 return experimental::get_underlying(__pt) != nullptr; 292} 293 294template <class _Tp> 295_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt) { 296 return nullptr != experimental::get_underlying(__pt); 297} 298 299template <class _Tp, class _Up> 300_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 301 return experimental::get_underlying(__pt) == experimental::get_underlying(__pu); 302} 303 304template <class _Tp, class _Up> 305_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 306 return experimental::get_underlying(__pt) != experimental::get_underlying(__pu); 307} 308 309template <class _Tp, class _Up> 310_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 311 return experimental::get_underlying(__pt) < experimental::get_underlying(__pu); 312} 313 314template <class _Tp, class _Up> 315_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 316 return experimental::get_underlying(__pt) > experimental::get_underlying(__pu); 317} 318 319template <class _Tp, class _Up> 320_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 321 return experimental::get_underlying(__pt) <= experimental::get_underlying(__pu); 322} 323 324template <class _Tp, class _Up> 325_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 326 return experimental::get_underlying(__pt) >= experimental::get_underlying(__pu); 327} 328 329template <class _Tp, class _Up> 330_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u) { 331 return experimental::get_underlying(__pt) == __u; 332} 333 334template <class _Tp, class _Up> 335_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) { 336 return experimental::get_underlying(__pt) != __u; 337} 338 339template <class _Tp, class _Up> 340_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u) { 341 return experimental::get_underlying(__pt) < __u; 342} 343 344template <class _Tp, class _Up> 345_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u) { 346 return experimental::get_underlying(__pt) > __u; 347} 348 349template <class _Tp, class _Up> 350_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) { 351 return experimental::get_underlying(__pt) <= __u; 352} 353 354template <class _Tp, class _Up> 355_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) { 356 return experimental::get_underlying(__pt) >= __u; 357} 358 359template <class _Tp, class _Up> 360_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu) { 361 return __t == experimental::get_underlying(__pu); 362} 363 364template <class _Tp, class _Up> 365_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) { 366 return __t != experimental::get_underlying(__pu); 367} 368 369template <class _Tp, class _Up> 370_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu) { 371 return __t < experimental::get_underlying(__pu); 372} 373 374template <class _Tp, class _Up> 375_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu) { 376 return __t > experimental::get_underlying(__pu); 377} 378 379template <class _Tp, class _Up> 380_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) { 381 return __t <= experimental::get_underlying(__pu); 382} 383 384template <class _Tp, class _Up> 385_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) { 386 return __t >= experimental::get_underlying(__pu); 387} 388 389template <class _Tp> 390_LIBCPP_HIDE_FROM_ABI constexpr void 391swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) noexcept(__is_nothrow_swappable_v<_Tp>) { 392 __pc1.swap(__pc2); 393} 394 395template <class _Tp> 396constexpr const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT { 397 return __pt.__t_; 398} 399 400template <class _Tp> 401constexpr _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT { 402 return __pt.__t_; 403} 404 405_LIBCPP_END_NAMESPACE_LFTS_V2 406 407_LIBCPP_BEGIN_NAMESPACE_STD 408 409template <class _Tp> 410struct hash<experimental::propagate_const<_Tp>> { 411 typedef size_t result_type; 412 typedef experimental::propagate_const<_Tp> argument_type; 413 414 _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::propagate_const<_Tp>& __pc1) const { 415 return std::hash<_Tp>()(experimental::get_underlying(__pc1)); 416 } 417}; 418 419template <class _Tp> 420struct equal_to<experimental::propagate_const<_Tp>> { 421 typedef experimental::propagate_const<_Tp> first_argument_type; 422 typedef experimental::propagate_const<_Tp> second_argument_type; 423 424 _LIBCPP_HIDE_FROM_ABI bool 425 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 426 return std::equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 427 } 428}; 429 430template <class _Tp> 431struct not_equal_to<experimental::propagate_const<_Tp>> { 432 typedef experimental::propagate_const<_Tp> first_argument_type; 433 typedef experimental::propagate_const<_Tp> second_argument_type; 434 435 _LIBCPP_HIDE_FROM_ABI bool 436 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 437 return std::not_equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 438 } 439}; 440 441template <class _Tp> 442struct less<experimental::propagate_const<_Tp>> { 443 typedef experimental::propagate_const<_Tp> first_argument_type; 444 typedef experimental::propagate_const<_Tp> second_argument_type; 445 446 _LIBCPP_HIDE_FROM_ABI bool 447 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 448 return std::less<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 449 } 450}; 451 452template <class _Tp> 453struct greater<experimental::propagate_const<_Tp>> { 454 typedef experimental::propagate_const<_Tp> first_argument_type; 455 typedef experimental::propagate_const<_Tp> second_argument_type; 456 457 _LIBCPP_HIDE_FROM_ABI bool 458 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 459 return std::greater<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 460 } 461}; 462 463template <class _Tp> 464struct less_equal<experimental::propagate_const<_Tp>> { 465 typedef experimental::propagate_const<_Tp> first_argument_type; 466 typedef experimental::propagate_const<_Tp> second_argument_type; 467 468 _LIBCPP_HIDE_FROM_ABI bool 469 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 470 return std::less_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 471 } 472}; 473 474template <class _Tp> 475struct greater_equal<experimental::propagate_const<_Tp>> { 476 typedef experimental::propagate_const<_Tp> first_argument_type; 477 typedef experimental::propagate_const<_Tp> second_argument_type; 478 479 _LIBCPP_HIDE_FROM_ABI bool 480 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 481 return std::greater_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 482 } 483}; 484 485_LIBCPP_END_NAMESPACE_STD 486 487# endif // _LIBCPP_STD_VER >= 14 488 489_LIBCPP_POP_MACROS 490 491# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 492# include <cstddef> 493# include <type_traits> 494# endif 495#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) 496 497#endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST 498