xref: /freebsd/contrib/llvm-project/libcxx/include/experimental/propagate_const (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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
220b57cec5SDimitry Andric    constexpr const _Tp& _VSTD_LFTS_V2::get_underlying(const propagate_const<T>& pt) noexcept;
230b57cec5SDimitry Andric    constexpr T& _VSTD_LFTS_V2::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
960b57cec5SDimitry Andric  template <class T> struct hash<experimental::fundamentals_v2::propagate_const<T>>;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric  // [propagate_const.comparison_function_objects], comparison function objects
990b57cec5SDimitry Andric  template <class T> struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;
1000b57cec5SDimitry Andric  template <class T> struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;
1010b57cec5SDimitry Andric  template <class T> struct less<experimental::fundamentals_v2::propagate_const<T>>;
1020b57cec5SDimitry Andric  template <class T> struct greater<experimental::fundamentals_v2::propagate_const<T>>;
1030b57cec5SDimitry Andric  template <class T> struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;
1040b57cec5SDimitry Andric  template <class T> struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric} // namespace std
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric*/
1090b57cec5SDimitry Andric
11081ad6265SDimitry Andric#include <__assert> // all public C++ headers provide the assertion handler
11181ad6265SDimitry Andric#include <__functional/operations.h>
112bdd1243dSDimitry Andric#include <__fwd/hash.h>
113*06c3fb27SDimitry Andric#include <__type_traits/conditional.h>
114*06c3fb27SDimitry Andric#include <__type_traits/decay.h>
115*06c3fb27SDimitry Andric#include <__type_traits/enable_if.h>
116*06c3fb27SDimitry Andric#include <__type_traits/is_array.h>
117*06c3fb27SDimitry Andric#include <__type_traits/is_constructible.h>
118*06c3fb27SDimitry Andric#include <__type_traits/is_convertible.h>
119*06c3fb27SDimitry Andric#include <__type_traits/is_function.h>
120*06c3fb27SDimitry Andric#include <__type_traits/is_pointer.h>
121*06c3fb27SDimitry Andric#include <__type_traits/is_reference.h>
122*06c3fb27SDimitry Andric#include <__type_traits/is_same.h>
123*06c3fb27SDimitry Andric#include <__type_traits/is_swappable.h>
124*06c3fb27SDimitry Andric#include <__type_traits/remove_cv.h>
125*06c3fb27SDimitry Andric#include <__type_traits/remove_pointer.h>
126*06c3fb27SDimitry Andric#include <__type_traits/remove_reference.h>
127*06c3fb27SDimitry Andric#include <__utility/declval.h>
12881ad6265SDimitry Andric#include <__utility/forward.h>
12981ad6265SDimitry Andric#include <__utility/move.h>
13081ad6265SDimitry Andric#include <__utility/swap.h>
131*06c3fb27SDimitry Andric#include <cstddef>
1320b57cec5SDimitry Andric#include <experimental/__config>
13304eeddc0SDimitry Andric
1340b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1350b57cec5SDimitry Andric#  pragma GCC system_header
1360b57cec5SDimitry Andric#endif
1370b57cec5SDimitry Andric
138*06c3fb27SDimitry Andric_LIBCPP_PUSH_MACROS
139*06c3fb27SDimitry Andric#include <__undef_macros>
140*06c3fb27SDimitry Andric
141*06c3fb27SDimitry Andric#if _LIBCPP_STD_VER >= 14
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andrictemplate <class _Tp>
1460b57cec5SDimitry Andricclass propagate_const;
1470b57cec5SDimitry Andric
1480b57cec5SDimitry Andrictemplate <class _Up>
1490b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
1500b57cec5SDimitry Andricconst _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andrictemplate <class _Up>
1530b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
1540b57cec5SDimitry Andric_Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andrictemplate <class _Tp>
1570b57cec5SDimitry Andricclass propagate_const
1580b57cec5SDimitry Andric{
1590b57cec5SDimitry Andricpublic:
160bdd1243dSDimitry Andric  typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric  static_assert(!is_array<_Tp>::value,
1630b57cec5SDimitry Andric      "Instantiation of propagate_const with an array type is ill-formed.");
1640b57cec5SDimitry Andric  static_assert(!is_reference<_Tp>::value,
1650b57cec5SDimitry Andric      "Instantiation of propagate_const with a reference type is ill-formed.");
166bdd1243dSDimitry Andric  static_assert(!(is_pointer<_Tp>::value && is_function<__remove_pointer_t<_Tp> >::value),
1670b57cec5SDimitry Andric      "Instantiation of propagate_const with a function-pointer type is ill-formed.");
168bdd1243dSDimitry Andric  static_assert(!(is_pointer<_Tp>::value && is_same<__remove_cv_t<__remove_pointer_t<_Tp> >, void>::value),
1690b57cec5SDimitry Andric      "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
1700b57cec5SDimitry Andric
1710b57cec5SDimitry Andricprivate:
1720b57cec5SDimitry Andric  template <class _Up>
173*06c3fb27SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u)
1740b57cec5SDimitry Andric  {
1750b57cec5SDimitry Andric    return __u;
1760b57cec5SDimitry Andric  }
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric  template <class _Up>
179*06c3fb27SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u)
1800b57cec5SDimitry Andric  {
1810b57cec5SDimitry Andric    return __get_pointer(__u.get());
1820b57cec5SDimitry Andric  }
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric  template <class _Up>
185*06c3fb27SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u)
1860b57cec5SDimitry Andric  {
1870b57cec5SDimitry Andric    return __u;
1880b57cec5SDimitry Andric  }
1890b57cec5SDimitry Andric
1900b57cec5SDimitry Andric  template <class _Up>
191*06c3fb27SDimitry Andric  static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u)
1920b57cec5SDimitry Andric  {
1930b57cec5SDimitry Andric    return __get_pointer(__u.get());
1940b57cec5SDimitry Andric  }
1950b57cec5SDimitry Andric
1960b57cec5SDimitry Andric  template <class _Up>
1970b57cec5SDimitry Andric  struct __is_propagate_const : false_type
1980b57cec5SDimitry Andric  {
1990b57cec5SDimitry Andric  };
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric  template <class _Up>
2020b57cec5SDimitry Andric  struct __is_propagate_const<propagate_const<_Up>> : true_type
2030b57cec5SDimitry Andric  {
2040b57cec5SDimitry Andric  };
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric  _Tp __t_;
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andricpublic:
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric  template <class _Up> friend _LIBCPP_CONSTEXPR const _Up& ::_VSTD_LFTS_V2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
2110b57cec5SDimitry Andric  template <class _Up> friend _LIBCPP_CONSTEXPR _Up& ::_VSTD_LFTS_V2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
2120b57cec5SDimitry Andric
213*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const() = default;
2140b57cec5SDimitry Andric
2150b57cec5SDimitry Andric  propagate_const(const propagate_const&) = delete;
2160b57cec5SDimitry Andric
217*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default;
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric  template <class _Up, enable_if_t<!is_convertible<_Up, _Tp>::value &&
2200b57cec5SDimitry Andric                                 is_constructible<_Tp, _Up&&>::value,bool> = true>
221*06c3fb27SDimitry Andric  explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
2220b57cec5SDimitry Andric      : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
2230b57cec5SDimitry Andric  {
2240b57cec5SDimitry Andric  }
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric  template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
2270b57cec5SDimitry Andric                                 is_constructible<_Tp, _Up&&>::value,bool> = false>
228*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
2290b57cec5SDimitry Andric      : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
2300b57cec5SDimitry Andric  {
2310b57cec5SDimitry Andric  }
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric  template <class _Up, enable_if_t<!is_convertible<_Up&&, _Tp>::value &&
2340b57cec5SDimitry Andric                                 is_constructible<_Tp, _Up&&>::value &&
2350b57cec5SDimitry Andric                                 !__is_propagate_const<decay_t<_Up>>::value,bool> = true>
236*06c3fb27SDimitry Andric  explicit _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
2370b57cec5SDimitry Andric      : __t_(std::forward<_Up>(__u))
2380b57cec5SDimitry Andric  {
2390b57cec5SDimitry Andric  }
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric  template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
2420b57cec5SDimitry Andric                                 is_constructible<_Tp, _Up&&>::value &&
2430b57cec5SDimitry Andric                                 !__is_propagate_const<decay_t<_Up>>::value,bool> = false>
244*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
2450b57cec5SDimitry Andric      : __t_(std::forward<_Up>(__u))
2460b57cec5SDimitry Andric  {
2470b57cec5SDimitry Andric  }
2480b57cec5SDimitry Andric
2490b57cec5SDimitry Andric  propagate_const& operator=(const propagate_const&) = delete;
2500b57cec5SDimitry Andric
251*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default;
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric  template <class _Up>
254*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu)
2550b57cec5SDimitry Andric  {
2560b57cec5SDimitry Andric    __t_ = std::move(_VSTD_LFTS_V2::get_underlying(__pu));
2570b57cec5SDimitry Andric    return *this;
2580b57cec5SDimitry Andric  }
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric  template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>>
261*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR propagate_const& operator=(_Up&& __u)
2620b57cec5SDimitry Andric  {
2630b57cec5SDimitry Andric    __t_ = std::forward<_Up>(__u);
2640b57cec5SDimitry Andric    return *this;
2650b57cec5SDimitry Andric  }
2660b57cec5SDimitry Andric
267*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* get() const
2680b57cec5SDimitry Andric  {
2690b57cec5SDimitry Andric    return __get_pointer(__t_);
2700b57cec5SDimitry Andric  }
2710b57cec5SDimitry Andric
272*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* get()
2730b57cec5SDimitry Andric  {
2740b57cec5SDimitry Andric    return __get_pointer(__t_);
2750b57cec5SDimitry Andric  }
2760b57cec5SDimitry Andric
277*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR operator bool() const
2780b57cec5SDimitry Andric  {
2790b57cec5SDimitry Andric    return get() != nullptr;
2800b57cec5SDimitry Andric  }
2810b57cec5SDimitry Andric
282*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type* operator->() const
2830b57cec5SDimitry Andric  {
2840b57cec5SDimitry Andric    return get();
2850b57cec5SDimitry Andric  }
2860b57cec5SDimitry Andric
287*06c3fb27SDimitry Andric  template <class _Dummy = _Tp, class _Up = enable_if_t<is_convertible<
288*06c3fb27SDimitry Andric                                  const _Dummy, const element_type *>::value>>
289*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator const element_type *() const {
2900b57cec5SDimitry Andric    return get();
2910b57cec5SDimitry Andric  }
2920b57cec5SDimitry Andric
293*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const element_type& operator*() const
2940b57cec5SDimitry Andric  {
2950b57cec5SDimitry Andric    return *get();
2960b57cec5SDimitry Andric  }
2970b57cec5SDimitry Andric
298*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type* operator->()
2990b57cec5SDimitry Andric  {
3000b57cec5SDimitry Andric    return get();
3010b57cec5SDimitry Andric  }
3020b57cec5SDimitry Andric
303*06c3fb27SDimitry Andric  template <class _Dummy = _Tp, class _Up = enable_if_t<
304*06c3fb27SDimitry Andric                                  is_convertible<_Dummy, element_type *>::value>>
305*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR operator element_type *() {
3060b57cec5SDimitry Andric    return get();
3070b57cec5SDimitry Andric  }
3080b57cec5SDimitry Andric
309*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR element_type& operator*()
3100b57cec5SDimitry Andric  {
3110b57cec5SDimitry Andric    return *get();
3120b57cec5SDimitry Andric  }
3130b57cec5SDimitry Andric
314*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR void swap(propagate_const& __pt)
315*06c3fb27SDimitry Andric      _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
3160b57cec5SDimitry Andric    using _VSTD::swap;
3170b57cec5SDimitry Andric    swap(__t_, __pt.__t_);
3180b57cec5SDimitry Andric  }
3190b57cec5SDimitry Andric};
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric
3220b57cec5SDimitry Andrictemplate <class _Tp>
3230b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3240b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, nullptr_t)
3250b57cec5SDimitry Andric{
3260b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) == nullptr;
3270b57cec5SDimitry Andric}
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andrictemplate <class _Tp>
3300b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3310b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator==(nullptr_t, const propagate_const<_Tp>& __pt)
3320b57cec5SDimitry Andric{
3330b57cec5SDimitry Andric  return nullptr == _VSTD_LFTS_V2::get_underlying(__pt);
3340b57cec5SDimitry Andric}
3350b57cec5SDimitry Andric
3360b57cec5SDimitry Andrictemplate <class _Tp>
3370b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3380b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
3390b57cec5SDimitry Andric{
3400b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) != nullptr;
3410b57cec5SDimitry Andric}
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andrictemplate <class _Tp>
3440b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3450b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt)
3460b57cec5SDimitry Andric{
3470b57cec5SDimitry Andric  return nullptr != _VSTD_LFTS_V2::get_underlying(__pt);
3480b57cec5SDimitry Andric}
3490b57cec5SDimitry Andric
3500b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3510b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3520b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt,
3530b57cec5SDimitry Andric                          const propagate_const<_Up>& __pu)
3540b57cec5SDimitry Andric{
3550b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) == _VSTD_LFTS_V2::get_underlying(__pu);
3560b57cec5SDimitry Andric}
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3590b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3600b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt,
3610b57cec5SDimitry Andric                          const propagate_const<_Up>& __pu)
3620b57cec5SDimitry Andric{
3630b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) != _VSTD_LFTS_V2::get_underlying(__pu);
3640b57cec5SDimitry Andric}
3650b57cec5SDimitry Andric
3660b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3670b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3680b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt,
3690b57cec5SDimitry Andric                         const propagate_const<_Up>& __pu)
3700b57cec5SDimitry Andric{
3710b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) < _VSTD_LFTS_V2::get_underlying(__pu);
3720b57cec5SDimitry Andric}
3730b57cec5SDimitry Andric
3740b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3750b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3760b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt,
3770b57cec5SDimitry Andric                         const propagate_const<_Up>& __pu)
3780b57cec5SDimitry Andric{
3790b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) > _VSTD_LFTS_V2::get_underlying(__pu);
3800b57cec5SDimitry Andric}
3810b57cec5SDimitry Andric
3820b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3830b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3840b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt,
3850b57cec5SDimitry Andric                          const propagate_const<_Up>& __pu)
3860b57cec5SDimitry Andric{
3870b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) <= _VSTD_LFTS_V2::get_underlying(__pu);
3880b57cec5SDimitry Andric}
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3910b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
3920b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt,
3930b57cec5SDimitry Andric                          const propagate_const<_Up>& __pu)
3940b57cec5SDimitry Andric{
3950b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) >= _VSTD_LFTS_V2::get_underlying(__pu);
3960b57cec5SDimitry Andric}
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
3990b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4000b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
4010b57cec5SDimitry Andric{
4020b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) == __u;
4030b57cec5SDimitry Andric}
4040b57cec5SDimitry Andric
4050b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4060b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4070b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
4080b57cec5SDimitry Andric{
4090b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) != __u;
4100b57cec5SDimitry Andric}
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4130b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4140b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
4150b57cec5SDimitry Andric{
4160b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) < __u;
4170b57cec5SDimitry Andric}
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4200b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4210b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
4220b57cec5SDimitry Andric{
4230b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) > __u;
4240b57cec5SDimitry Andric}
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4270b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4280b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
4290b57cec5SDimitry Andric{
4300b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) <= __u;
4310b57cec5SDimitry Andric}
4320b57cec5SDimitry Andric
4330b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4340b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4350b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
4360b57cec5SDimitry Andric{
4370b57cec5SDimitry Andric  return _VSTD_LFTS_V2::get_underlying(__pt) >= __u;
4380b57cec5SDimitry Andric}
4390b57cec5SDimitry Andric
4400b57cec5SDimitry Andric
4410b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4420b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4430b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
4440b57cec5SDimitry Andric{
4450b57cec5SDimitry Andric  return __t == _VSTD_LFTS_V2::get_underlying(__pu);
4460b57cec5SDimitry Andric}
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4490b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4500b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
4510b57cec5SDimitry Andric{
4520b57cec5SDimitry Andric  return __t != _VSTD_LFTS_V2::get_underlying(__pu);
4530b57cec5SDimitry Andric}
4540b57cec5SDimitry Andric
4550b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4560b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4570b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
4580b57cec5SDimitry Andric{
4590b57cec5SDimitry Andric  return __t < _VSTD_LFTS_V2::get_underlying(__pu);
4600b57cec5SDimitry Andric}
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4630b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4640b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
4650b57cec5SDimitry Andric{
4660b57cec5SDimitry Andric  return __t > _VSTD_LFTS_V2::get_underlying(__pu);
4670b57cec5SDimitry Andric}
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4700b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4710b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
4720b57cec5SDimitry Andric{
4730b57cec5SDimitry Andric  return __t <= _VSTD_LFTS_V2::get_underlying(__pu);
4740b57cec5SDimitry Andric}
4750b57cec5SDimitry Andric
4760b57cec5SDimitry Andrictemplate <class _Tp, class _Up>
4770b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4780b57cec5SDimitry Andric_LIBCPP_CONSTEXPR bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
4790b57cec5SDimitry Andric{
4800b57cec5SDimitry Andric  return __t >= _VSTD_LFTS_V2::get_underlying(__pu);
4810b57cec5SDimitry Andric}
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andrictemplate <class _Tp>
4840b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
4850b57cec5SDimitry Andric_LIBCPP_CONSTEXPR void swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
4860b57cec5SDimitry Andric{
4870b57cec5SDimitry Andric  __pc1.swap(__pc2);
4880b57cec5SDimitry Andric}
4890b57cec5SDimitry Andric
4900b57cec5SDimitry Andrictemplate <class _Tp>
4910b57cec5SDimitry Andric_LIBCPP_CONSTEXPR const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT
4920b57cec5SDimitry Andric{
4930b57cec5SDimitry Andric  return __pt.__t_;
4940b57cec5SDimitry Andric}
4950b57cec5SDimitry Andric
4960b57cec5SDimitry Andrictemplate <class _Tp>
4970b57cec5SDimitry Andric_LIBCPP_CONSTEXPR _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT
4980b57cec5SDimitry Andric{
4990b57cec5SDimitry Andric  return __pt.__t_;
5000b57cec5SDimitry Andric}
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_LFTS_V2
5030b57cec5SDimitry Andric
5040b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
5050b57cec5SDimitry Andric
5060b57cec5SDimitry Andrictemplate <class _Tp>
5070b57cec5SDimitry Andricstruct hash<experimental::fundamentals_v2::propagate_const<_Tp>>
5080b57cec5SDimitry Andric{
5090b57cec5SDimitry Andric  typedef size_t result_type;
5100b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> argument_type;
5110b57cec5SDimitry Andric
512*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const
5130b57cec5SDimitry Andric  {
5140b57cec5SDimitry Andric    return std::hash<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1));
5150b57cec5SDimitry Andric  }
5160b57cec5SDimitry Andric};
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andrictemplate <class _Tp>
5190b57cec5SDimitry Andricstruct equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
5200b57cec5SDimitry Andric{
5210b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
5220b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
5230b57cec5SDimitry Andric
524*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
5250b57cec5SDimitry Andric      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
5260b57cec5SDimitry Andric  {
5270b57cec5SDimitry Andric    return std::equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
5280b57cec5SDimitry Andric  }
5290b57cec5SDimitry Andric};
5300b57cec5SDimitry Andric
5310b57cec5SDimitry Andrictemplate <class _Tp>
5320b57cec5SDimitry Andricstruct not_equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
5330b57cec5SDimitry Andric{
5340b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
5350b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
5360b57cec5SDimitry Andric
537*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
5380b57cec5SDimitry Andric      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
5390b57cec5SDimitry Andric  {
5400b57cec5SDimitry Andric    return std::not_equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
5410b57cec5SDimitry Andric  }
5420b57cec5SDimitry Andric};
5430b57cec5SDimitry Andric
5440b57cec5SDimitry Andrictemplate <class _Tp>
5450b57cec5SDimitry Andricstruct less<experimental::fundamentals_v2::propagate_const<_Tp>>
5460b57cec5SDimitry Andric{
5470b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
5480b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
5490b57cec5SDimitry Andric
550*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
5510b57cec5SDimitry Andric      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
5520b57cec5SDimitry Andric  {
5530b57cec5SDimitry Andric    return std::less<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
5540b57cec5SDimitry Andric  }
5550b57cec5SDimitry Andric};
5560b57cec5SDimitry Andric
5570b57cec5SDimitry Andrictemplate <class _Tp>
5580b57cec5SDimitry Andricstruct greater<experimental::fundamentals_v2::propagate_const<_Tp>>
5590b57cec5SDimitry Andric{
5600b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
5610b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
5620b57cec5SDimitry Andric
563*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
5640b57cec5SDimitry Andric      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
5650b57cec5SDimitry Andric  {
5660b57cec5SDimitry Andric    return std::greater<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
5670b57cec5SDimitry Andric  }
5680b57cec5SDimitry Andric};
5690b57cec5SDimitry Andric
5700b57cec5SDimitry Andrictemplate <class _Tp>
5710b57cec5SDimitry Andricstruct less_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
5720b57cec5SDimitry Andric{
5730b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
5740b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
5750b57cec5SDimitry Andric
576*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
5770b57cec5SDimitry Andric      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
5780b57cec5SDimitry Andric  {
5790b57cec5SDimitry Andric    return std::less_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
5800b57cec5SDimitry Andric  }
5810b57cec5SDimitry Andric};
5820b57cec5SDimitry Andric
5830b57cec5SDimitry Andrictemplate <class _Tp>
5840b57cec5SDimitry Andricstruct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
5850b57cec5SDimitry Andric{
5860b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
5870b57cec5SDimitry Andric  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
5880b57cec5SDimitry Andric
589*06c3fb27SDimitry Andric  _LIBCPP_HIDE_FROM_ABI bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
5900b57cec5SDimitry Andric      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
5910b57cec5SDimitry Andric  {
5920b57cec5SDimitry Andric    return std::greater_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
5930b57cec5SDimitry Andric  }
5940b57cec5SDimitry Andric};
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
5970b57cec5SDimitry Andric
598*06c3fb27SDimitry Andric#endif // _LIBCPP_STD_VER >= 14
599*06c3fb27SDimitry Andric
600*06c3fb27SDimitry Andric_LIBCPP_POP_MACROS
601*06c3fb27SDimitry Andric
602*06c3fb27SDimitry Andric#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
603*06c3fb27SDimitry Andric#  include <type_traits>
604*06c3fb27SDimitry Andric#endif
605*06c3fb27SDimitry Andric
6060b57cec5SDimitry Andric#endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
607