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#include <__functional/operations.h> 111#include <__fwd/functional.h> 112#include <__type_traits/conditional.h> 113#include <__type_traits/decay.h> 114#include <__type_traits/enable_if.h> 115#include <__type_traits/is_array.h> 116#include <__type_traits/is_constructible.h> 117#include <__type_traits/is_convertible.h> 118#include <__type_traits/is_function.h> 119#include <__type_traits/is_pointer.h> 120#include <__type_traits/is_reference.h> 121#include <__type_traits/is_same.h> 122#include <__type_traits/is_swappable.h> 123#include <__type_traits/remove_cv.h> 124#include <__type_traits/remove_pointer.h> 125#include <__type_traits/remove_reference.h> 126#include <__utility/declval.h> 127#include <__utility/forward.h> 128#include <__utility/move.h> 129#include <__utility/swap.h> 130#include <cstddef> 131#include <experimental/__config> 132 133#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 134# pragma GCC system_header 135#endif 136 137_LIBCPP_PUSH_MACROS 138#include <__undef_macros> 139 140#if _LIBCPP_STD_VER >= 14 141 142_LIBCPP_BEGIN_NAMESPACE_LFTS_V2 143 144template <class _Tp> 145class propagate_const; 146 147template <class _Up> 148inline _LIBCPP_HIDE_FROM_ABI constexpr const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT; 149 150template <class _Up> 151inline _LIBCPP_HIDE_FROM_ABI constexpr _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT; 152 153template <class _Tp> 154class propagate_const { 155public: 156 typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type; 157 158 static_assert(!is_array<_Tp>::value, "Instantiation of propagate_const with an array type is ill-formed."); 159 static_assert(!is_reference<_Tp>::value, "Instantiation of propagate_const with a reference type is ill-formed."); 160 static_assert(!(is_pointer<_Tp>::value && is_function<__remove_pointer_t<_Tp> >::value), 161 "Instantiation of propagate_const with a function-pointer type is ill-formed."); 162 static_assert(!(is_pointer<_Tp>::value && is_same<__remove_cv_t<__remove_pointer_t<_Tp> >, void>::value), 163 "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed."); 164 165private: 166 template <class _Up> 167 static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up* __u) { 168 return __u; 169 } 170 171 template <class _Up> 172 static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up& __u) { 173 return __get_pointer(__u.get()); 174 } 175 176 template <class _Up> 177 static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up* __u) { 178 return __u; 179 } 180 181 template <class _Up> 182 static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up& __u) { 183 return __get_pointer(__u.get()); 184 } 185 186 template <class _Up> 187 struct __is_propagate_const : false_type {}; 188 189 template <class _Up> 190 struct __is_propagate_const<propagate_const<_Up>> : true_type {}; 191 192 _Tp __t_; 193 194public: 195 template <class _Up> 196 friend constexpr const _Up& experimental::fundamentals_v2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT; 197 template <class _Up> 198 friend constexpr _Up& experimental::fundamentals_v2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT; 199 200 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const() = default; 201 202 propagate_const(const propagate_const&) = delete; 203 204 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const&&) = default; 205 206 template <class _Up, 207 enable_if_t<!is_convertible<_Up, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = true> 208 explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu) 209 : __t_(std::move(experimental::get_underlying(__pu))) {} 210 211 template <class _Up, 212 enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = false> 213 _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 && 218 !__is_propagate_const<decay_t<_Up>>::value, 219 bool> = true> 220 explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {} 221 222 template <class _Up, 223 enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value && 224 !__is_propagate_const<decay_t<_Up>>::value, 225 bool> = false> 226 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {} 227 228 propagate_const& operator=(const propagate_const&) = delete; 229 230 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const&&) = default; 231 232 template <class _Up> 233 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) { 234 __t_ = std::move(experimental::get_underlying(__pu)); 235 return *this; 236 } 237 238 template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>> 239 _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(_Up&& __u) { 240 __t_ = std::forward<_Up>(__u); 241 return *this; 242 } 243 244 _LIBCPP_HIDE_FROM_ABI constexpr const element_type* get() const { return __get_pointer(__t_); } 245 246 _LIBCPP_HIDE_FROM_ABI constexpr element_type* get() { return __get_pointer(__t_); } 247 248 _LIBCPP_HIDE_FROM_ABI explicit constexpr operator bool() const { return get() != nullptr; } 249 250 _LIBCPP_HIDE_FROM_ABI constexpr const element_type* operator->() const { return get(); } 251 252 template <class _Dummy = _Tp, class _Up = enable_if_t<is_convertible< const _Dummy, const element_type*>::value>> 253 _LIBCPP_HIDE_FROM_ABI constexpr operator const element_type*() const { 254 return get(); 255 } 256 257 _LIBCPP_HIDE_FROM_ABI constexpr const element_type& operator*() const { return *get(); } 258 259 _LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() { return get(); } 260 261 template <class _Dummy = _Tp, class _Up = enable_if_t< is_convertible<_Dummy, element_type*>::value>> 262 _LIBCPP_HIDE_FROM_ABI constexpr operator element_type*() { 263 return get(); 264 } 265 266 _LIBCPP_HIDE_FROM_ABI constexpr element_type& operator*() { return *get(); } 267 268 _LIBCPP_HIDE_FROM_ABI constexpr void swap(propagate_const& __pt) noexcept(__is_nothrow_swappable_v<_Tp>) { 269 using std::swap; 270 swap(__t_, __pt.__t_); 271 } 272}; 273 274template <class _Tp> 275_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, nullptr_t) { 276 return experimental::get_underlying(__pt) == nullptr; 277} 278 279template <class _Tp> 280_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullptr_t, const propagate_const<_Tp>& __pt) { 281 return nullptr == experimental::get_underlying(__pt); 282} 283 284template <class _Tp> 285_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t) { 286 return experimental::get_underlying(__pt) != nullptr; 287} 288 289template <class _Tp> 290_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt) { 291 return nullptr != experimental::get_underlying(__pt); 292} 293 294template <class _Tp, class _Up> 295_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { 296 return experimental::get_underlying(__pt) == experimental::get_underlying(__pu); 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 _Up& __u) { 326 return experimental::get_underlying(__pt) == __u; 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 _Tp& __t, const propagate_const<_Up>& __pu) { 356 return __t == experimental::get_underlying(__pu); 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> 385_LIBCPP_HIDE_FROM_ABI constexpr void 386swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) noexcept(__is_nothrow_swappable_v<_Tp>) { 387 __pc1.swap(__pc2); 388} 389 390template <class _Tp> 391constexpr const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT { 392 return __pt.__t_; 393} 394 395template <class _Tp> 396constexpr _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT { 397 return __pt.__t_; 398} 399 400_LIBCPP_END_NAMESPACE_LFTS_V2 401 402_LIBCPP_BEGIN_NAMESPACE_STD 403 404template <class _Tp> 405struct hash<experimental::propagate_const<_Tp>> { 406 typedef size_t result_type; 407 typedef experimental::propagate_const<_Tp> argument_type; 408 409 _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::propagate_const<_Tp>& __pc1) const { 410 return std::hash<_Tp>()(experimental::get_underlying(__pc1)); 411 } 412}; 413 414template <class _Tp> 415struct equal_to<experimental::propagate_const<_Tp>> { 416 typedef experimental::propagate_const<_Tp> first_argument_type; 417 typedef experimental::propagate_const<_Tp> second_argument_type; 418 419 _LIBCPP_HIDE_FROM_ABI bool 420 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 421 return std::equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 422 } 423}; 424 425template <class _Tp> 426struct not_equal_to<experimental::propagate_const<_Tp>> { 427 typedef experimental::propagate_const<_Tp> first_argument_type; 428 typedef experimental::propagate_const<_Tp> second_argument_type; 429 430 _LIBCPP_HIDE_FROM_ABI bool 431 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 432 return std::not_equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 433 } 434}; 435 436template <class _Tp> 437struct less<experimental::propagate_const<_Tp>> { 438 typedef experimental::propagate_const<_Tp> first_argument_type; 439 typedef experimental::propagate_const<_Tp> second_argument_type; 440 441 _LIBCPP_HIDE_FROM_ABI bool 442 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 443 return std::less<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 444 } 445}; 446 447template <class _Tp> 448struct greater<experimental::propagate_const<_Tp>> { 449 typedef experimental::propagate_const<_Tp> first_argument_type; 450 typedef experimental::propagate_const<_Tp> second_argument_type; 451 452 _LIBCPP_HIDE_FROM_ABI bool 453 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 454 return std::greater<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 455 } 456}; 457 458template <class _Tp> 459struct less_equal<experimental::propagate_const<_Tp>> { 460 typedef experimental::propagate_const<_Tp> first_argument_type; 461 typedef experimental::propagate_const<_Tp> second_argument_type; 462 463 _LIBCPP_HIDE_FROM_ABI bool 464 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 465 return std::less_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 466 } 467}; 468 469template <class _Tp> 470struct greater_equal<experimental::propagate_const<_Tp>> { 471 typedef experimental::propagate_const<_Tp> first_argument_type; 472 typedef experimental::propagate_const<_Tp> second_argument_type; 473 474 _LIBCPP_HIDE_FROM_ABI bool 475 operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const { 476 return std::greater_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2)); 477 } 478}; 479 480_LIBCPP_END_NAMESPACE_STD 481 482#endif // _LIBCPP_STD_VER >= 14 483 484_LIBCPP_POP_MACROS 485 486#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 487# include <type_traits> 488#endif 489 490#endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST 491