xref: /freebsd/contrib/llvm-project/libcxx/include/experimental/propagate_const (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric// -*- C++ -*-
2349cc55cSDimitry Andric//===----------------------------------------------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
110b57cec5SDimitry Andric#define _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
1281ad6265SDimitry Andric
130b57cec5SDimitry Andric/*
140b57cec5SDimitry Andric    propagate_const synopsis
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric    namespace std { namespace experimental { inline namespace fundamentals_v2 {
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric    // [propagate_const]
190b57cec5SDimitry Andric    template <class T> class propagate_const;
200b57cec5SDimitry Andric
210b57cec5SDimitry Andric    // [propagate_const.underlying], underlying pointer access
225f757f3fSDimitry Andric    constexpr const _Tp& get_underlying(const propagate_const<T>& pt) noexcept;
235f757f3fSDimitry Andric    constexpr T& get_underlying(propagate_const<T>& pt) noexcept;
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric    // [propagate_const.relational], relational operators
260b57cec5SDimitry Andric    template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
270b57cec5SDimitry Andric    template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);
280b57cec5SDimitry Andric    template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
290b57cec5SDimitry Andric    template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu);
300b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
310b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
320b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
330b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
340b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
350b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
360b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const _Up& u);
370b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const _Up& u);
380b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const _Up& u);
390b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const _Up& u);
400b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const _Up& u);
410b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const _Up& u);
420b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator==(const _Tp& t, const propagate_const<_Up>& pu);
430b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator!=(const _Tp& t, const propagate_const<_Up>& pu);
440b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator<(const _Tp& t, const propagate_const<_Up>& pu);
450b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator>(const _Tp& t, const propagate_const<_Up>& pu);
460b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator<=(const _Tp& t, const propagate_const<_Up>& pu);
470b57cec5SDimitry Andric    template <class T, class U> constexpr bool operator>=(const _Tp& t, const propagate_const<_Up>& pu);
480b57cec5SDimitry Andric
490b57cec5SDimitry Andric    // [propagate_const.algorithms], specialized algorithms
500b57cec5SDimitry Andric    template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below);
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric    template <class T>
530b57cec5SDimitry Andric    class propagate_const
540b57cec5SDimitry Andric    {
550b57cec5SDimitry Andric
560b57cec5SDimitry Andric    public:
570b57cec5SDimitry Andric      typedef remove_reference_t<decltype(*declval<T&>())> element_type;
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric      // [propagate_const.ctor], constructors
600b57cec5SDimitry Andric      constexpr propagate_const() = default;
610b57cec5SDimitry Andric      propagate_const(const propagate_const& p) = delete;
620b57cec5SDimitry Andric      constexpr propagate_const(propagate_const&& p) = default;
630b57cec5SDimitry Andric      template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below
640b57cec5SDimitry Andric      template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric      // [propagate_const.assignment], assignment
670b57cec5SDimitry Andric      propagate_const& operator=(const propagate_const& p) = delete;
680b57cec5SDimitry Andric      constexpr propagate_const& operator=(propagate_const&& p) = default;
690b57cec5SDimitry Andric      template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu);
700b57cec5SDimitry Andric      template <class U> constexpr propagate_const& operator=(U&& u); // see below
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric      // [propagate_const.const_observers], const observers
730b57cec5SDimitry Andric      explicit constexpr operator bool() const;
740b57cec5SDimitry Andric      constexpr const element_type* operator->() const;
750b57cec5SDimitry Andric      constexpr operator const element_type*() const; // Not always defined
760b57cec5SDimitry Andric      constexpr const element_type& operator*() const;
770b57cec5SDimitry Andric      constexpr const element_type* get() const;
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric      // [propagate_const.non_const_observers], non-const observers
800b57cec5SDimitry Andric      constexpr element_type* operator->();
810b57cec5SDimitry Andric      constexpr operator element_type*(); // Not always defined
820b57cec5SDimitry Andric      constexpr element_type& operator*();
830b57cec5SDimitry Andric      constexpr element_type* get();
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric      // [propagate_const.modifiers], modifiers
860b57cec5SDimitry Andric      constexpr void swap(propagate_const& pt) noexcept(see below)
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric    private:
890b57cec5SDimitry Andric      T t_; // exposition only
900b57cec5SDimitry Andric    };
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric  } // namespace fundamentals_v2
930b57cec5SDimitry Andric  } // namespace experimental
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric  // [propagate_const.hash], hash support
965f757f3fSDimitry Andric  template <class T> struct hash<experimental::propagate_const<T>>;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric  // [propagate_const.comparison_function_objects], comparison function objects
995f757f3fSDimitry Andric  template <class T> struct equal_to<experimental::propagate_const<T>>;
1005f757f3fSDimitry Andric  template <class T> struct not_equal_to<experimental::propagate_const<T>>;
1015f757f3fSDimitry Andric  template <class T> struct less<experimental::propagate_const<T>>;
1025f757f3fSDimitry Andric  template <class T> struct greater<experimental::propagate_const<T>>;
1035f757f3fSDimitry Andric  template <class T> struct less_equal<experimental::propagate_const<T>>;
1045f757f3fSDimitry Andric  template <class T> struct greater_equal<experimental::propagate_const<T>>;
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric} // namespace std
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric*/
1090b57cec5SDimitry Andric
11081ad6265SDimitry Andric#include <__functional/operations.h>
111*0fca6ea1SDimitry Andric#include <__fwd/functional.h>
11206c3fb27SDimitry Andric#include <__type_traits/conditional.h>
11306c3fb27SDimitry Andric#include <__type_traits/decay.h>
11406c3fb27SDimitry Andric#include <__type_traits/enable_if.h>
11506c3fb27SDimitry Andric#include <__type_traits/is_array.h>
11606c3fb27SDimitry Andric#include <__type_traits/is_constructible.h>
11706c3fb27SDimitry Andric#include <__type_traits/is_convertible.h>
11806c3fb27SDimitry Andric#include <__type_traits/is_function.h>
11906c3fb27SDimitry Andric#include <__type_traits/is_pointer.h>
12006c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
12106c3fb27SDimitry Andric#include <__type_traits/is_same.h>
12206c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
12306c3fb27SDimitry Andric#include <__type_traits/remove_cv.h>
12406c3fb27SDimitry Andric#include <__type_traits/remove_pointer.h>
12506c3fb27SDimitry Andric#include <__type_traits/remove_reference.h>
12606c3fb27SDimitry Andric#include <__utility/declval.h>
12781ad6265SDimitry Andric#include <__utility/forward.h>
12881ad6265SDimitry Andric#include <__utility/move.h>
12981ad6265SDimitry Andric#include <__utility/swap.h>
13006c3fb27SDimitry Andric#include <cstddef>
1310b57cec5SDimitry Andric#include <experimental/__config>
13204eeddc0SDimitry Andric
1330b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1340b57cec5SDimitry Andric#  pragma GCC system_header
1350b57cec5SDimitry Andric#endif
1360b57cec5SDimitry Andric
13706c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS
13806c3fb27SDimitry Andric#include <__undef_macros>
13906c3fb27SDimitry Andric
14006c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 14
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andrictemplate <class _Tp>
1450b57cec5SDimitry Andricclass propagate_const;
1460b57cec5SDimitry Andric
1470b57cec5SDimitry Andrictemplate <class _Up>
148*0fca6ea1SDimitry Andricinline _LIBCPP_HIDE_FROM_ABI constexpr const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andrictemplate <class _Up>
151*0fca6ea1SDimitry Andricinline _LIBCPP_HIDE_FROM_ABI constexpr _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andrictemplate <class _Tp>
154cb14a3feSDimitry Andricclass propagate_const {
1550b57cec5SDimitry Andricpublic:
156bdd1243dSDimitry Andric  typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
1570b57cec5SDimitry Andric
158cb14a3feSDimitry Andric  static_assert(!is_array<_Tp>::value, "Instantiation of propagate_const with an array type is ill-formed.");
159cb14a3feSDimitry Andric  static_assert(!is_reference<_Tp>::value, "Instantiation of propagate_const with a reference type is ill-formed.");
160bdd1243dSDimitry Andric  static_assert(!(is_pointer<_Tp>::value && is_function<__remove_pointer_t<_Tp> >::value),
1610b57cec5SDimitry Andric                "Instantiation of propagate_const with a function-pointer type is ill-formed.");
162bdd1243dSDimitry Andric  static_assert(!(is_pointer<_Tp>::value && is_same<__remove_cv_t<__remove_pointer_t<_Tp> >, void>::value),
1630b57cec5SDimitry Andric                "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andricprivate:
1660b57cec5SDimitry Andric  template <class _Up>
167*0fca6ea1SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up* __u) {
1680b57cec5SDimitry Andric    return __u;
1690b57cec5SDimitry Andric  }
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andric  template <class _Up>
172*0fca6ea1SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI constexpr element_type* __get_pointer(_Up& __u) {
1730b57cec5SDimitry Andric    return __get_pointer(__u.get());
1740b57cec5SDimitry Andric  }
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric  template <class _Up>
177*0fca6ea1SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up* __u) {
1780b57cec5SDimitry Andric    return __u;
1790b57cec5SDimitry Andric  }
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andric  template <class _Up>
182*0fca6ea1SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI constexpr const element_type* __get_pointer(const _Up& __u) {
1830b57cec5SDimitry Andric    return __get_pointer(__u.get());
1840b57cec5SDimitry Andric  }
1850b57cec5SDimitry Andric
1860b57cec5SDimitry Andric  template <class _Up>
187cb14a3feSDimitry Andric  struct __is_propagate_const : false_type {};
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric  template <class _Up>
190cb14a3feSDimitry Andric  struct __is_propagate_const<propagate_const<_Up>> : true_type {};
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric  _Tp __t_;
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andricpublic:
195cb14a3feSDimitry Andric  template <class _Up>
196*0fca6ea1SDimitry Andric  friend constexpr const _Up& experimental::fundamentals_v2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
197cb14a3feSDimitry Andric  template <class _Up>
198*0fca6ea1SDimitry Andric  friend constexpr _Up& experimental::fundamentals_v2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
1990b57cec5SDimitry Andric
200*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const() = default;
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric  propagate_const(const propagate_const&) = delete;
2030b57cec5SDimitry Andric
204*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const&&) = default;
2050b57cec5SDimitry Andric
206cb14a3feSDimitry Andric  template <class _Up,
207cb14a3feSDimitry Andric            enable_if_t<!is_convertible<_Up, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = true>
208*0fca6ea1SDimitry Andric  explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu)
209cb14a3feSDimitry Andric      : __t_(std::move(experimental::get_underlying(__pu))) {}
2100b57cec5SDimitry Andric
211cb14a3feSDimitry Andric  template <class _Up,
212cb14a3feSDimitry Andric            enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value, bool> = false>
213*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(propagate_const<_Up>&& __pu)
214cb14a3feSDimitry Andric      : __t_(std::move(experimental::get_underlying(__pu))) {}
2150b57cec5SDimitry Andric
216cb14a3feSDimitry Andric  template <class _Up,
217cb14a3feSDimitry Andric            enable_if_t<!is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value &&
218cb14a3feSDimitry Andric                            !__is_propagate_const<decay_t<_Up>>::value,
219cb14a3feSDimitry Andric                        bool> = true>
220*0fca6ea1SDimitry Andric  explicit _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {}
2210b57cec5SDimitry Andric
222cb14a3feSDimitry Andric  template <class _Up,
223cb14a3feSDimitry Andric            enable_if_t<is_convertible<_Up&&, _Tp>::value && is_constructible<_Tp, _Up&&>::value &&
224cb14a3feSDimitry Andric                            !__is_propagate_const<decay_t<_Up>>::value,
225cb14a3feSDimitry Andric                        bool> = false>
226*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const(_Up&& __u) : __t_(std::forward<_Up>(__u)) {}
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric  propagate_const& operator=(const propagate_const&) = delete;
2290b57cec5SDimitry Andric
230*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const&&) = default;
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric  template <class _Up>
233*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) {
2345f757f3fSDimitry Andric    __t_ = std::move(experimental::get_underlying(__pu));
2350b57cec5SDimitry Andric    return *this;
2360b57cec5SDimitry Andric  }
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric  template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>>
239*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr propagate_const& operator=(_Up&& __u) {
2400b57cec5SDimitry Andric    __t_ = std::forward<_Up>(__u);
2410b57cec5SDimitry Andric    return *this;
2420b57cec5SDimitry Andric  }
2430b57cec5SDimitry Andric
244*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const element_type* get() const { return __get_pointer(__t_); }
2450b57cec5SDimitry Andric
246*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr element_type* get() { return __get_pointer(__t_); }
2470b57cec5SDimitry Andric
248*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit constexpr operator bool() const { return get() != nullptr; }
2490b57cec5SDimitry Andric
250*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const element_type* operator->() const { return get(); }
2510b57cec5SDimitry Andric
252cb14a3feSDimitry Andric  template <class _Dummy = _Tp, class _Up = enable_if_t<is_convertible< const _Dummy, const element_type*>::value>>
253*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr operator const element_type*() const {
2540b57cec5SDimitry Andric    return get();
2550b57cec5SDimitry Andric  }
2560b57cec5SDimitry Andric
257*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr const element_type& operator*() const { return *get(); }
2580b57cec5SDimitry Andric
259*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr element_type* operator->() { return get(); }
2600b57cec5SDimitry Andric
261cb14a3feSDimitry Andric  template <class _Dummy = _Tp, class _Up = enable_if_t< is_convertible<_Dummy, element_type*>::value>>
262*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr operator element_type*() {
2630b57cec5SDimitry Andric    return get();
2640b57cec5SDimitry Andric  }
2650b57cec5SDimitry Andric
266*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr element_type& operator*() { return *get(); }
2670b57cec5SDimitry Andric
268*0fca6ea1SDimitry Andric  _LIBCPP_HIDE_FROM_ABI constexpr void swap(propagate_const& __pt) noexcept(__is_nothrow_swappable_v<_Tp>) {
2695f757f3fSDimitry Andric    using std::swap;
2700b57cec5SDimitry Andric    swap(__t_, __pt.__t_);
2710b57cec5SDimitry Andric  }
2720b57cec5SDimitry Andric};
2730b57cec5SDimitry Andric
2740b57cec5SDimitry Andrictemplate <class _Tp>
275*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, nullptr_t) {
2765f757f3fSDimitry Andric  return experimental::get_underlying(__pt) == nullptr;
2770b57cec5SDimitry Andric}
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andrictemplate <class _Tp>
280*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(nullptr_t, const propagate_const<_Tp>& __pt) {
2815f757f3fSDimitry Andric  return nullptr == experimental::get_underlying(__pt);
2820b57cec5SDimitry Andric}
2830b57cec5SDimitry Andric
2840b57cec5SDimitry Andrictemplate <class _Tp>
285*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t) {
2865f757f3fSDimitry Andric  return experimental::get_underlying(__pt) != nullptr;
2870b57cec5SDimitry Andric}
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andrictemplate <class _Tp>
290*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt) {
2915f757f3fSDimitry Andric  return nullptr != experimental::get_underlying(__pt);
2920b57cec5SDimitry Andric}
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
295*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
2965f757f3fSDimitry Andric  return experimental::get_underlying(__pt) == experimental::get_underlying(__pu);
2970b57cec5SDimitry Andric}
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
300*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
3015f757f3fSDimitry Andric  return experimental::get_underlying(__pt) != experimental::get_underlying(__pu);
3020b57cec5SDimitry Andric}
3030b57cec5SDimitry Andric
3040b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
305*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
3065f757f3fSDimitry Andric  return experimental::get_underlying(__pt) < experimental::get_underlying(__pu);
3070b57cec5SDimitry Andric}
3080b57cec5SDimitry Andric
3090b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
310*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
3115f757f3fSDimitry Andric  return experimental::get_underlying(__pt) > experimental::get_underlying(__pu);
3120b57cec5SDimitry Andric}
3130b57cec5SDimitry Andric
3140b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
315*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
3165f757f3fSDimitry Andric  return experimental::get_underlying(__pt) <= experimental::get_underlying(__pu);
3170b57cec5SDimitry Andric}
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
320*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) {
3215f757f3fSDimitry Andric  return experimental::get_underlying(__pt) >= experimental::get_underlying(__pu);
3220b57cec5SDimitry Andric}
3230b57cec5SDimitry Andric
3240b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
325*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u) {
3265f757f3fSDimitry Andric  return experimental::get_underlying(__pt) == __u;
3270b57cec5SDimitry Andric}
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
330*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) {
3315f757f3fSDimitry Andric  return experimental::get_underlying(__pt) != __u;
3320b57cec5SDimitry Andric}
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
335*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u) {
3365f757f3fSDimitry Andric  return experimental::get_underlying(__pt) < __u;
3370b57cec5SDimitry Andric}
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
340*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u) {
3415f757f3fSDimitry Andric  return experimental::get_underlying(__pt) > __u;
3420b57cec5SDimitry Andric}
3430b57cec5SDimitry Andric
3440b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
345*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) {
3465f757f3fSDimitry Andric  return experimental::get_underlying(__pt) <= __u;
3470b57cec5SDimitry Andric}
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
350*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) {
3515f757f3fSDimitry Andric  return experimental::get_underlying(__pt) >= __u;
3520b57cec5SDimitry Andric}
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
355*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu) {
3565f757f3fSDimitry Andric  return __t == experimental::get_underlying(__pu);
3570b57cec5SDimitry Andric}
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
360*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) {
3615f757f3fSDimitry Andric  return __t != experimental::get_underlying(__pu);
3620b57cec5SDimitry Andric}
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
365*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu) {
3665f757f3fSDimitry Andric  return __t < experimental::get_underlying(__pu);
3670b57cec5SDimitry Andric}
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
370*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu) {
3715f757f3fSDimitry Andric  return __t > experimental::get_underlying(__pu);
3720b57cec5SDimitry Andric}
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
375*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) {
3765f757f3fSDimitry Andric  return __t <= experimental::get_underlying(__pu);
3770b57cec5SDimitry Andric}
3780b57cec5SDimitry Andric
3790b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
380*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) {
3815f757f3fSDimitry Andric  return __t >= experimental::get_underlying(__pu);
3820b57cec5SDimitry Andric}
3830b57cec5SDimitry Andric
3840b57cec5SDimitry Andrictemplate <class _Tp>
385*0fca6ea1SDimitry Andric_LIBCPP_HIDE_FROM_ABI constexpr void
386*0fca6ea1SDimitry Andricswap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) noexcept(__is_nothrow_swappable_v<_Tp>) {
3870b57cec5SDimitry Andric  __pc1.swap(__pc2);
3880b57cec5SDimitry Andric}
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andrictemplate <class _Tp>
391*0fca6ea1SDimitry Andricconstexpr const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT {
3920b57cec5SDimitry Andric  return __pt.__t_;
3930b57cec5SDimitry Andric}
3940b57cec5SDimitry Andric
3950b57cec5SDimitry Andrictemplate <class _Tp>
396*0fca6ea1SDimitry Andricconstexpr _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT {
3970b57cec5SDimitry Andric  return __pt.__t_;
3980b57cec5SDimitry Andric}
3990b57cec5SDimitry Andric
4000b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_LFTS_V2
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
4030b57cec5SDimitry Andric
4040b57cec5SDimitry Andrictemplate <class _Tp>
405cb14a3feSDimitry Andricstruct hash<experimental::propagate_const<_Tp>> {
4060b57cec5SDimitry Andric  typedef size_t result_type;
4075f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> argument_type;
4080b57cec5SDimitry Andric
409cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::propagate_const<_Tp>& __pc1) const {
4105f757f3fSDimitry Andric    return std::hash<_Tp>()(experimental::get_underlying(__pc1));
4110b57cec5SDimitry Andric  }
4120b57cec5SDimitry Andric};
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andrictemplate <class _Tp>
415cb14a3feSDimitry Andricstruct equal_to<experimental::propagate_const<_Tp>> {
4165f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> first_argument_type;
4175f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> second_argument_type;
4180b57cec5SDimitry Andric
419cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool
420cb14a3feSDimitry Andric  operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
4215f757f3fSDimitry Andric    return std::equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
4220b57cec5SDimitry Andric  }
4230b57cec5SDimitry Andric};
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andrictemplate <class _Tp>
426cb14a3feSDimitry Andricstruct not_equal_to<experimental::propagate_const<_Tp>> {
4275f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> first_argument_type;
4285f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> second_argument_type;
4290b57cec5SDimitry Andric
430cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool
431cb14a3feSDimitry Andric  operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
4325f757f3fSDimitry Andric    return std::not_equal_to<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
4330b57cec5SDimitry Andric  }
4340b57cec5SDimitry Andric};
4350b57cec5SDimitry Andric
4360b57cec5SDimitry Andrictemplate <class _Tp>
437cb14a3feSDimitry Andricstruct less<experimental::propagate_const<_Tp>> {
4385f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> first_argument_type;
4395f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> second_argument_type;
4400b57cec5SDimitry Andric
441cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool
442cb14a3feSDimitry Andric  operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
4435f757f3fSDimitry Andric    return std::less<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
4440b57cec5SDimitry Andric  }
4450b57cec5SDimitry Andric};
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andrictemplate <class _Tp>
448cb14a3feSDimitry Andricstruct greater<experimental::propagate_const<_Tp>> {
4495f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> first_argument_type;
4505f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> second_argument_type;
4510b57cec5SDimitry Andric
452cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool
453cb14a3feSDimitry Andric  operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
4545f757f3fSDimitry Andric    return std::greater<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
4550b57cec5SDimitry Andric  }
4560b57cec5SDimitry Andric};
4570b57cec5SDimitry Andric
4580b57cec5SDimitry Andrictemplate <class _Tp>
459cb14a3feSDimitry Andricstruct less_equal<experimental::propagate_const<_Tp>> {
4605f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> first_argument_type;
4615f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> second_argument_type;
4620b57cec5SDimitry Andric
463cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool
464cb14a3feSDimitry Andric  operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
4655f757f3fSDimitry Andric    return std::less_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
4660b57cec5SDimitry Andric  }
4670b57cec5SDimitry Andric};
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andrictemplate <class _Tp>
470cb14a3feSDimitry Andricstruct greater_equal<experimental::propagate_const<_Tp>> {
4715f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> first_argument_type;
4725f757f3fSDimitry Andric  typedef experimental::propagate_const<_Tp> second_argument_type;
4730b57cec5SDimitry Andric
474cb14a3feSDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool
475cb14a3feSDimitry Andric  operator()(const experimental::propagate_const<_Tp>& __pc1, const experimental::propagate_const<_Tp>& __pc2) const {
4765f757f3fSDimitry Andric    return std::greater_equal<_Tp>()(experimental::get_underlying(__pc1), experimental::get_underlying(__pc2));
4770b57cec5SDimitry Andric  }
4780b57cec5SDimitry Andric};
4790b57cec5SDimitry Andric
4800b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
4810b57cec5SDimitry Andric
48206c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 14
48306c3fb27SDimitry Andric
48406c3fb27SDimitry Andric_LIBCPP_POP_MACROS
48506c3fb27SDimitry Andric
48606c3fb27SDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
48706c3fb27SDimitry Andric#  include <type_traits>
48806c3fb27SDimitry Andric#endif
48906c3fb27SDimitry Andric
4900b57cec5SDimitry Andric#endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
491