Home | History | Annotate | Line # | Download | only in experimental
      1 // -*- C++ -*-
      2 //===------------------------ propagate_const -----------------------------===//
      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     propagate_const synopsis
     14 
     15     namespace std { namespace experimental { inline namespace fundamentals_v2 {
     16 
     17     // [propagate_const]
     18     template <class T> class propagate_const;
     19 
     20     // [propagate_const.underlying], underlying pointer access
     21     constexpr const _Tp& _VSTD_LFTS_V2::get_underlying(const propagate_const<T>& pt) noexcept;
     22     constexpr T& _VSTD_LFTS_V2::get_underlying(propagate_const<T>& pt) noexcept;
     23 
     24     // [propagate_const.relational], relational operators
     25     template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
     26     template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);
     27     template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
     28     template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu);
     29     template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<_Up>& 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 _Up& u);
     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 _Tp& t, const propagate_const<_Up>& pu);
     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 
     48     // [propagate_const.algorithms], specialized algorithms
     49     template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below);
     50 
     51     template <class T>
     52     class propagate_const
     53     {
     54 
     55     public:
     56       typedef remove_reference_t<decltype(*declval<T&>())> element_type;
     57 
     58       // [propagate_const.ctor], constructors
     59       constexpr propagate_const() = default;
     60       propagate_const(const propagate_const& p) = delete;
     61       constexpr propagate_const(propagate_const&& p) = default;
     62       template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below
     63       template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below
     64 
     65       // [propagate_const.assignment], assignment
     66       propagate_const& operator=(const propagate_const& p) = delete;
     67       constexpr propagate_const& operator=(propagate_const&& p) = default;
     68       template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu);
     69       template <class U> constexpr propagate_const& operator=(U&& u); // see below
     70 
     71       // [propagate_const.const_observers], const observers
     72       explicit constexpr operator bool() const;
     73       constexpr const element_type* operator->() const;
     74       constexpr operator const element_type*() const; // Not always defined
     75       constexpr const element_type& operator*() const;
     76       constexpr const element_type* get() const;
     77 
     78       // [propagate_const.non_const_observers], non-const observers
     79       constexpr element_type* operator->();
     80       constexpr operator element_type*(); // Not always defined
     81       constexpr element_type& operator*();
     82       constexpr element_type* get();
     83 
     84       // [propagate_const.modifiers], modifiers
     85       constexpr void swap(propagate_const& pt) noexcept(see below)
     86 
     87     private:
     88       T t_; // exposition only
     89     };
     90 
     91   } // namespace fundamentals_v2
     92   } // namespace experimental
     93 
     94   // [propagate_const.hash], hash support
     95   template <class T> struct hash<experimental::fundamentals_v2::propagate_const<T>>;
     96 
     97   // [propagate_const.comparison_function_objects], comparison function objects
     98   template <class T> struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;
     99   template <class T> struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;
    100   template <class T> struct less<experimental::fundamentals_v2::propagate_const<T>>;
    101   template <class T> struct greater<experimental::fundamentals_v2::propagate_const<T>>;
    102   template <class T> struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;
    103   template <class T> struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;
    104 
    105 } // namespace std
    106 
    107 */
    108 
    109 #include <experimental/__config>
    110 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
    111 #pragma GCC system_header
    112 #endif
    113 
    114 #if _LIBCPP_STD_VER > 11
    115 
    116 #include <type_traits>
    117 #include <utility>
    118 #include <functional>
    119 
    120 _LIBCPP_BEGIN_NAMESPACE_LFTS_V2
    121 
    122 
    123 template <class _Tp>
    124 class propagate_const;
    125 
    126 template <class _Up>
    127 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    128 const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
    129 
    130 template <class _Up>
    131 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
    132 _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
    133 
    134 template <class _Tp>
    135 class propagate_const
    136 {
    137 public:
    138   typedef remove_reference_t<decltype(*declval<_Tp&>())> element_type;
    139 
    140   static_assert(!is_array<_Tp>::value,
    141       "Instantiation of propagate_const with an array type is ill-formed.");
    142   static_assert(!is_reference<_Tp>::value,
    143       "Instantiation of propagate_const with a reference type is ill-formed.");
    144   static_assert(!(is_pointer<_Tp>::value && is_function<typename remove_pointer<_Tp>::type>::value),
    145       "Instantiation of propagate_const with a function-pointer type is ill-formed.");
    146   static_assert(!(is_pointer<_Tp>::value && is_same<typename remove_cv<typename remove_pointer<_Tp>::type>::type, void>::value),
    147       "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
    148 
    149 private:
    150   template <class _Up>
    151   static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u)
    152   {
    153     return __u;
    154   }
    155 
    156   template <class _Up>
    157   static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u)
    158   {
    159     return __get_pointer(__u.get());
    160   }
    161 
    162   template <class _Up>
    163   static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u)
    164   {
    165     return __u;
    166   }
    167 
    168   template <class _Up>
    169   static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u)
    170   {
    171     return __get_pointer(__u.get());
    172   }
    173 
    174   template <class _Up>
    175   struct __is_propagate_const : false_type
    176   {
    177   };
    178 
    179   template <class _Up>
    180   struct __is_propagate_const<propagate_const<_Up>> : true_type
    181   {
    182   };
    183 
    184   _Tp __t_;
    185 
    186 public:
    187 
    188   template <class _Up> friend _LIBCPP_CONSTEXPR const _Up& ::_VSTD_LFTS_V2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
    189   template <class _Up> friend _LIBCPP_CONSTEXPR _Up& ::_VSTD_LFTS_V2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
    190 
    191   _LIBCPP_CONSTEXPR propagate_const() = default;
    192 
    193   propagate_const(const propagate_const&) = delete;
    194 
    195   _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default;
    196 
    197   template <class _Up, enable_if_t<!is_convertible<_Up, _Tp>::value &&
    198                                  is_constructible<_Tp, _Up&&>::value,bool> = true>
    199   explicit _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
    200       : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
    201   {
    202   }
    203 
    204   template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
    205                                  is_constructible<_Tp, _Up&&>::value,bool> = false>
    206   _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
    207       : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
    208   {
    209   }
    210 
    211   template <class _Up, enable_if_t<!is_convertible<_Up&&, _Tp>::value &&
    212                                  is_constructible<_Tp, _Up&&>::value &&
    213                                  !__is_propagate_const<decay_t<_Up>>::value,bool> = true>
    214   explicit _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
    215       : __t_(std::forward<_Up>(__u))
    216   {
    217   }
    218 
    219   template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
    220                                  is_constructible<_Tp, _Up&&>::value &&
    221                                  !__is_propagate_const<decay_t<_Up>>::value,bool> = false>
    222   _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
    223       : __t_(std::forward<_Up>(__u))
    224   {
    225   }
    226 
    227   propagate_const& operator=(const propagate_const&) = delete;
    228 
    229   _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default;
    230 
    231   template <class _Up>
    232   _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu)
    233   {
    234     __t_ = std::move(_VSTD_LFTS_V2::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_CONSTEXPR propagate_const& operator=(_Up&& __u)
    240   {
    241     __t_ = std::forward<_Up>(__u);
    242     return *this;
    243   }
    244 
    245   _LIBCPP_CONSTEXPR const element_type* get() const
    246   {
    247     return __get_pointer(__t_);
    248   }
    249 
    250   _LIBCPP_CONSTEXPR element_type* get()
    251   {
    252     return __get_pointer(__t_);
    253   }
    254 
    255   explicit _LIBCPP_CONSTEXPR operator bool() const
    256   {
    257     return get() != nullptr;
    258   }
    259 
    260   _LIBCPP_CONSTEXPR const element_type* operator->() const
    261   {
    262     return get();
    263   }
    264 
    265   template <class _Tp_ = _Tp, class _Up = enable_if_t<is_convertible<
    266                                   const _Tp_, const element_type *>::value>>
    267   _LIBCPP_CONSTEXPR operator const element_type *() const {
    268     return get();
    269   }
    270 
    271   _LIBCPP_CONSTEXPR const element_type& operator*() const
    272   {
    273     return *get();
    274   }
    275 
    276   _LIBCPP_CONSTEXPR element_type* operator->()
    277   {
    278     return get();
    279   }
    280 
    281   template <class _Tp_ = _Tp, class _Up = enable_if_t<
    282                                   is_convertible<_Tp_, element_type *>::value>>
    283   _LIBCPP_CONSTEXPR operator element_type *() {
    284     return get();
    285   }
    286 
    287   _LIBCPP_CONSTEXPR element_type& operator*()
    288   {
    289     return *get();
    290   }
    291 
    292   _LIBCPP_CONSTEXPR void swap(propagate_const& __pt) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
    293   {
    294     using _VSTD::swap;
    295     swap(__t_, __pt.__t_);
    296   }
    297 };
    298 
    299 
    300 template <class _Tp>
    301 _LIBCPP_INLINE_VISIBILITY
    302 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, nullptr_t)
    303 {
    304   return _VSTD_LFTS_V2::get_underlying(__pt) == nullptr;
    305 }
    306 
    307 template <class _Tp>
    308 _LIBCPP_INLINE_VISIBILITY
    309 _LIBCPP_CONSTEXPR bool operator==(nullptr_t, const propagate_const<_Tp>& __pt)
    310 {
    311   return nullptr == _VSTD_LFTS_V2::get_underlying(__pt);
    312 }
    313 
    314 template <class _Tp>
    315 _LIBCPP_INLINE_VISIBILITY
    316 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
    317 {
    318   return _VSTD_LFTS_V2::get_underlying(__pt) != nullptr;
    319 }
    320 
    321 template <class _Tp>
    322 _LIBCPP_INLINE_VISIBILITY
    323 _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt)
    324 {
    325   return nullptr != _VSTD_LFTS_V2::get_underlying(__pt);
    326 }
    327 
    328 template <class _Tp, class _Up>
    329 _LIBCPP_INLINE_VISIBILITY
    330 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt,
    331                           const propagate_const<_Up>& __pu)
    332 {
    333   return _VSTD_LFTS_V2::get_underlying(__pt) == _VSTD_LFTS_V2::get_underlying(__pu);
    334 }
    335 
    336 template <class _Tp, class _Up>
    337 _LIBCPP_INLINE_VISIBILITY
    338 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt,
    339                           const propagate_const<_Up>& __pu)
    340 {
    341   return _VSTD_LFTS_V2::get_underlying(__pt) != _VSTD_LFTS_V2::get_underlying(__pu);
    342 }
    343 
    344 template <class _Tp, class _Up>
    345 _LIBCPP_INLINE_VISIBILITY
    346 _LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt,
    347                          const propagate_const<_Up>& __pu)
    348 {
    349   return _VSTD_LFTS_V2::get_underlying(__pt) < _VSTD_LFTS_V2::get_underlying(__pu);
    350 }
    351 
    352 template <class _Tp, class _Up>
    353 _LIBCPP_INLINE_VISIBILITY
    354 _LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt,
    355                          const propagate_const<_Up>& __pu)
    356 {
    357   return _VSTD_LFTS_V2::get_underlying(__pt) > _VSTD_LFTS_V2::get_underlying(__pu);
    358 }
    359 
    360 template <class _Tp, class _Up>
    361 _LIBCPP_INLINE_VISIBILITY
    362 _LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt,
    363                           const propagate_const<_Up>& __pu)
    364 {
    365   return _VSTD_LFTS_V2::get_underlying(__pt) <= _VSTD_LFTS_V2::get_underlying(__pu);
    366 }
    367 
    368 template <class _Tp, class _Up>
    369 _LIBCPP_INLINE_VISIBILITY
    370 _LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt,
    371                           const propagate_const<_Up>& __pu)
    372 {
    373   return _VSTD_LFTS_V2::get_underlying(__pt) >= _VSTD_LFTS_V2::get_underlying(__pu);
    374 }
    375 
    376 template <class _Tp, class _Up>
    377 _LIBCPP_INLINE_VISIBILITY
    378 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
    379 {
    380   return _VSTD_LFTS_V2::get_underlying(__pt) == __u;
    381 }
    382 
    383 template <class _Tp, class _Up>
    384 _LIBCPP_INLINE_VISIBILITY
    385 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
    386 {
    387   return _VSTD_LFTS_V2::get_underlying(__pt) != __u;
    388 }
    389 
    390 template <class _Tp, class _Up>
    391 _LIBCPP_INLINE_VISIBILITY
    392 _LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
    393 {
    394   return _VSTD_LFTS_V2::get_underlying(__pt) < __u;
    395 }
    396 
    397 template <class _Tp, class _Up>
    398 _LIBCPP_INLINE_VISIBILITY
    399 _LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
    400 {
    401   return _VSTD_LFTS_V2::get_underlying(__pt) > __u;
    402 }
    403 
    404 template <class _Tp, class _Up>
    405 _LIBCPP_INLINE_VISIBILITY
    406 _LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
    407 {
    408   return _VSTD_LFTS_V2::get_underlying(__pt) <= __u;
    409 }
    410 
    411 template <class _Tp, class _Up>
    412 _LIBCPP_INLINE_VISIBILITY
    413 _LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
    414 {
    415   return _VSTD_LFTS_V2::get_underlying(__pt) >= __u;
    416 }
    417 
    418 
    419 template <class _Tp, class _Up>
    420 _LIBCPP_INLINE_VISIBILITY
    421 _LIBCPP_CONSTEXPR bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
    422 {
    423   return __t == _VSTD_LFTS_V2::get_underlying(__pu);
    424 }
    425 
    426 template <class _Tp, class _Up>
    427 _LIBCPP_INLINE_VISIBILITY
    428 _LIBCPP_CONSTEXPR bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
    429 {
    430   return __t != _VSTD_LFTS_V2::get_underlying(__pu);
    431 }
    432 
    433 template <class _Tp, class _Up>
    434 _LIBCPP_INLINE_VISIBILITY
    435 _LIBCPP_CONSTEXPR bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
    436 {
    437   return __t < _VSTD_LFTS_V2::get_underlying(__pu);
    438 }
    439 
    440 template <class _Tp, class _Up>
    441 _LIBCPP_INLINE_VISIBILITY
    442 _LIBCPP_CONSTEXPR bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
    443 {
    444   return __t > _VSTD_LFTS_V2::get_underlying(__pu);
    445 }
    446 
    447 template <class _Tp, class _Up>
    448 _LIBCPP_INLINE_VISIBILITY
    449 _LIBCPP_CONSTEXPR bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
    450 {
    451   return __t <= _VSTD_LFTS_V2::get_underlying(__pu);
    452 }
    453 
    454 template <class _Tp, class _Up>
    455 _LIBCPP_INLINE_VISIBILITY
    456 _LIBCPP_CONSTEXPR bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
    457 {
    458   return __t >= _VSTD_LFTS_V2::get_underlying(__pu);
    459 }
    460 
    461 template <class _Tp>
    462 _LIBCPP_INLINE_VISIBILITY
    463 _LIBCPP_CONSTEXPR void swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
    464 {
    465   __pc1.swap(__pc2);
    466 }
    467 
    468 template <class _Tp>
    469 _LIBCPP_CONSTEXPR const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT
    470 {
    471   return __pt.__t_;
    472 }
    473 
    474 template <class _Tp>
    475 _LIBCPP_CONSTEXPR _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT
    476 {
    477   return __pt.__t_;
    478 }
    479 
    480 _LIBCPP_END_NAMESPACE_LFTS_V2
    481 
    482 _LIBCPP_BEGIN_NAMESPACE_STD
    483 
    484 template <class _Tp>
    485 struct hash<experimental::fundamentals_v2::propagate_const<_Tp>>
    486 {
    487   typedef size_t result_type;
    488   typedef experimental::fundamentals_v2::propagate_const<_Tp> argument_type;
    489 
    490   size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const
    491   {
    492     return std::hash<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1));
    493   }
    494 };
    495 
    496 template <class _Tp>
    497 struct equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
    498 {
    499   typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
    500   typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
    501 
    502   bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
    503       const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
    504   {
    505     return std::equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
    506   }
    507 };
    508 
    509 template <class _Tp>
    510 struct not_equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
    511 {
    512   typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
    513   typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
    514 
    515   bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
    516       const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
    517   {
    518     return std::not_equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
    519   }
    520 };
    521 
    522 template <class _Tp>
    523 struct less<experimental::fundamentals_v2::propagate_const<_Tp>>
    524 {
    525   typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
    526   typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
    527 
    528   bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
    529       const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
    530   {
    531     return std::less<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
    532   }
    533 };
    534 
    535 template <class _Tp>
    536 struct greater<experimental::fundamentals_v2::propagate_const<_Tp>>
    537 {
    538   typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
    539   typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
    540 
    541   bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
    542       const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
    543   {
    544     return std::greater<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
    545   }
    546 };
    547 
    548 template <class _Tp>
    549 struct less_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
    550 {
    551   typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
    552   typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
    553 
    554   bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
    555       const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
    556   {
    557     return std::less_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
    558   }
    559 };
    560 
    561 template <class _Tp>
    562 struct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
    563 {
    564   typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
    565   typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
    566 
    567   bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
    568       const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
    569   {
    570     return std::greater_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
    571   }
    572 };
    573 
    574 _LIBCPP_END_NAMESPACE_STD
    575 
    576 #endif // _LIBCPP_STD_VER > 11
    577 #endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
    578