1945cacc8SJonathan Coe// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
3945cacc8SJonathan Coe//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7945cacc8SJonathan Coe//
8945cacc8SJonathan Coe//===----------------------------------------------------------------------===//
9945cacc8SJonathan Coe
10945cacc8SJonathan Coe#ifndef _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
11945cacc8SJonathan Coe#define _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
12385cc25aSLouis Dionne
13945cacc8SJonathan Coe/*
14945cacc8SJonathan Coe    propagate_const synopsis
15945cacc8SJonathan Coe
16945cacc8SJonathan Coe    namespace std { namespace experimental { inline namespace fundamentals_v2 {
17945cacc8SJonathan Coe
18945cacc8SJonathan Coe    // [propagate_const]
19945cacc8SJonathan Coe    template <class T> class propagate_const;
20945cacc8SJonathan Coe
21945cacc8SJonathan Coe    // [propagate_const.underlying], underlying pointer access
22945cacc8SJonathan Coe    constexpr const _Tp& _VSTD_LFTS_V2::get_underlying(const propagate_const<T>& pt) noexcept;
23945cacc8SJonathan Coe    constexpr T& _VSTD_LFTS_V2::get_underlying(propagate_const<T>& pt) noexcept;
24945cacc8SJonathan Coe
25945cacc8SJonathan Coe    // [propagate_const.relational], relational operators
26945cacc8SJonathan Coe    template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
27945cacc8SJonathan Coe    template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);
28945cacc8SJonathan Coe    template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
29945cacc8SJonathan Coe    template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu);
30945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
31945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
32945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
33945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
34945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
35945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
36945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const _Up& u);
37945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const _Up& u);
38945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const _Up& u);
39945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const _Up& u);
40945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const _Up& u);
41945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const _Up& u);
42945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator==(const _Tp& t, const propagate_const<_Up>& pu);
43945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator!=(const _Tp& t, const propagate_const<_Up>& pu);
44945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator<(const _Tp& t, const propagate_const<_Up>& pu);
45945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator>(const _Tp& t, const propagate_const<_Up>& pu);
46945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator<=(const _Tp& t, const propagate_const<_Up>& pu);
47945cacc8SJonathan Coe    template <class T, class U> constexpr bool operator>=(const _Tp& t, const propagate_const<_Up>& pu);
48945cacc8SJonathan Coe
49945cacc8SJonathan Coe    // [propagate_const.algorithms], specialized algorithms
50945cacc8SJonathan Coe    template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below);
51945cacc8SJonathan Coe
52945cacc8SJonathan Coe    template <class T>
53945cacc8SJonathan Coe    class propagate_const
54945cacc8SJonathan Coe    {
55945cacc8SJonathan Coe
56945cacc8SJonathan Coe    public:
57945cacc8SJonathan Coe      typedef remove_reference_t<decltype(*declval<T&>())> element_type;
58945cacc8SJonathan Coe
59945cacc8SJonathan Coe      // [propagate_const.ctor], constructors
60945cacc8SJonathan Coe      constexpr propagate_const() = default;
61945cacc8SJonathan Coe      propagate_const(const propagate_const& p) = delete;
62945cacc8SJonathan Coe      constexpr propagate_const(propagate_const&& p) = default;
63945cacc8SJonathan Coe      template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below
64945cacc8SJonathan Coe      template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below
65945cacc8SJonathan Coe
66945cacc8SJonathan Coe      // [propagate_const.assignment], assignment
67945cacc8SJonathan Coe      propagate_const& operator=(const propagate_const& p) = delete;
68945cacc8SJonathan Coe      constexpr propagate_const& operator=(propagate_const&& p) = default;
69945cacc8SJonathan Coe      template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu);
70945cacc8SJonathan Coe      template <class U> constexpr propagate_const& operator=(U&& u); // see below
71945cacc8SJonathan Coe
72945cacc8SJonathan Coe      // [propagate_const.const_observers], const observers
73945cacc8SJonathan Coe      explicit constexpr operator bool() const;
74945cacc8SJonathan Coe      constexpr const element_type* operator->() const;
75945cacc8SJonathan Coe      constexpr operator const element_type*() const; // Not always defined
76945cacc8SJonathan Coe      constexpr const element_type& operator*() const;
77945cacc8SJonathan Coe      constexpr const element_type* get() const;
78945cacc8SJonathan Coe
79945cacc8SJonathan Coe      // [propagate_const.non_const_observers], non-const observers
80945cacc8SJonathan Coe      constexpr element_type* operator->();
81945cacc8SJonathan Coe      constexpr operator element_type*(); // Not always defined
82945cacc8SJonathan Coe      constexpr element_type& operator*();
83945cacc8SJonathan Coe      constexpr element_type* get();
84945cacc8SJonathan Coe
85945cacc8SJonathan Coe      // [propagate_const.modifiers], modifiers
86945cacc8SJonathan Coe      constexpr void swap(propagate_const& pt) noexcept(see below)
87945cacc8SJonathan Coe
88945cacc8SJonathan Coe    private:
89945cacc8SJonathan Coe      T t_; // exposition only
90945cacc8SJonathan Coe    };
91945cacc8SJonathan Coe
92945cacc8SJonathan Coe  } // namespace fundamentals_v2
93945cacc8SJonathan Coe  } // namespace experimental
94945cacc8SJonathan Coe
95945cacc8SJonathan Coe  // [propagate_const.hash], hash support
96945cacc8SJonathan Coe  template <class T> struct hash<experimental::fundamentals_v2::propagate_const<T>>;
97945cacc8SJonathan Coe
98945cacc8SJonathan Coe  // [propagate_const.comparison_function_objects], comparison function objects
99945cacc8SJonathan Coe  template <class T> struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;
100945cacc8SJonathan Coe  template <class T> struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;
101945cacc8SJonathan Coe  template <class T> struct less<experimental::fundamentals_v2::propagate_const<T>>;
102945cacc8SJonathan Coe  template <class T> struct greater<experimental::fundamentals_v2::propagate_const<T>>;
103945cacc8SJonathan Coe  template <class T> struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;
104945cacc8SJonathan Coe  template <class T> struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;
105945cacc8SJonathan Coe
106945cacc8SJonathan Coe} // namespace std
107945cacc8SJonathan Coe
108945cacc8SJonathan Coe*/
109945cacc8SJonathan Coe
110385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
111*faef447eSNikolas Klauser#include <__functional/operations.h>
112*faef447eSNikolas Klauser#include <__utility/forward.h>
11352915d78SNikolas Klauser#include <__utility/move.h>
11452915d78SNikolas Klauser#include <__utility/swap.h>
115945cacc8SJonathan Coe#include <experimental/__config>
1164d81a46fSArthur O'Dwyer#include <type_traits>
11752915d78SNikolas Klauser
118945cacc8SJonathan Coe#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
119945cacc8SJonathan Coe#  pragma GCC system_header
120945cacc8SJonathan Coe#endif
121945cacc8SJonathan Coe
122945cacc8SJonathan Coe#if _LIBCPP_STD_VER > 11
123945cacc8SJonathan Coe
124945cacc8SJonathan Coe_LIBCPP_BEGIN_NAMESPACE_LFTS_V2
125945cacc8SJonathan Coe
126945cacc8SJonathan Coetemplate <class _Tp>
127945cacc8SJonathan Coeclass propagate_const;
128e0d2d58fSEric Fiselier
129e0d2d58fSEric Fiseliertemplate <class _Up>
130e0d2d58fSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
131e0d2d58fSEric Fiselierconst _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
132e0d2d58fSEric Fiselier
133e0d2d58fSEric Fiseliertemplate <class _Up>
134e0d2d58fSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
135e0d2d58fSEric Fiselier_Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
136945cacc8SJonathan Coe
137945cacc8SJonathan Coetemplate <class _Tp>
138945cacc8SJonathan Coeclass propagate_const
139945cacc8SJonathan Coe{
140945cacc8SJonathan Coepublic:
141ab3fcc50SArthur O'Dwyer  typedef remove_reference_t<decltype(*declval<_Tp&>())> element_type;
142945cacc8SJonathan Coe
143945cacc8SJonathan Coe  static_assert(!is_array<_Tp>::value,
144945cacc8SJonathan Coe      "Instantiation of propagate_const with an array type is ill-formed.");
145945cacc8SJonathan Coe  static_assert(!is_reference<_Tp>::value,
146945cacc8SJonathan Coe      "Instantiation of propagate_const with a reference type is ill-formed.");
147945cacc8SJonathan Coe  static_assert(!(is_pointer<_Tp>::value && is_function<typename remove_pointer<_Tp>::type>::value),
148945cacc8SJonathan Coe      "Instantiation of propagate_const with a function-pointer type is ill-formed.");
149945cacc8SJonathan Coe  static_assert(!(is_pointer<_Tp>::value && is_same<typename remove_cv<typename remove_pointer<_Tp>::type>::type, void>::value),
150945cacc8SJonathan Coe      "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
151945cacc8SJonathan Coe
152945cacc8SJonathan Coeprivate:
153945cacc8SJonathan Coe  template <class _Up>
154945cacc8SJonathan Coe  static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u)
155945cacc8SJonathan Coe  {
156945cacc8SJonathan Coe    return __u;
157945cacc8SJonathan Coe  }
158945cacc8SJonathan Coe
159945cacc8SJonathan Coe  template <class _Up>
160945cacc8SJonathan Coe  static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u)
161945cacc8SJonathan Coe  {
162945cacc8SJonathan Coe    return __get_pointer(__u.get());
163945cacc8SJonathan Coe  }
164945cacc8SJonathan Coe
165945cacc8SJonathan Coe  template <class _Up>
166945cacc8SJonathan Coe  static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u)
167945cacc8SJonathan Coe  {
168945cacc8SJonathan Coe    return __u;
169945cacc8SJonathan Coe  }
170945cacc8SJonathan Coe
171945cacc8SJonathan Coe  template <class _Up>
172945cacc8SJonathan Coe  static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u)
173945cacc8SJonathan Coe  {
174945cacc8SJonathan Coe    return __get_pointer(__u.get());
175945cacc8SJonathan Coe  }
176945cacc8SJonathan Coe
177945cacc8SJonathan Coe  template <class _Up>
178945cacc8SJonathan Coe  struct __is_propagate_const : false_type
179945cacc8SJonathan Coe  {
180945cacc8SJonathan Coe  };
181945cacc8SJonathan Coe
182945cacc8SJonathan Coe  template <class _Up>
183945cacc8SJonathan Coe  struct __is_propagate_const<propagate_const<_Up>> : true_type
184945cacc8SJonathan Coe  {
185945cacc8SJonathan Coe  };
186945cacc8SJonathan Coe
187945cacc8SJonathan Coe  _Tp __t_;
188945cacc8SJonathan Coe
189945cacc8SJonathan Coepublic:
190945cacc8SJonathan Coe
191945cacc8SJonathan Coe  template <class _Up> friend _LIBCPP_CONSTEXPR const _Up& ::_VSTD_LFTS_V2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
192945cacc8SJonathan Coe  template <class _Up> friend _LIBCPP_CONSTEXPR _Up& ::_VSTD_LFTS_V2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
193945cacc8SJonathan Coe
194945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const() = default;
195945cacc8SJonathan Coe
196945cacc8SJonathan Coe  propagate_const(const propagate_const&) = delete;
197945cacc8SJonathan Coe
198945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default;
199945cacc8SJonathan Coe
200945cacc8SJonathan Coe  template <class _Up, enable_if_t<!is_convertible<_Up, _Tp>::value &&
201945cacc8SJonathan Coe                                 is_constructible<_Tp, _Up&&>::value,bool> = true>
202945cacc8SJonathan Coe  explicit _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
203945cacc8SJonathan Coe      : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
204945cacc8SJonathan Coe  {
205945cacc8SJonathan Coe  }
206945cacc8SJonathan Coe
207945cacc8SJonathan Coe  template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
208945cacc8SJonathan Coe                                 is_constructible<_Tp, _Up&&>::value,bool> = false>
209945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
210945cacc8SJonathan Coe      : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
211945cacc8SJonathan Coe  {
212945cacc8SJonathan Coe  }
213945cacc8SJonathan Coe
214945cacc8SJonathan Coe  template <class _Up, enable_if_t<!is_convertible<_Up&&, _Tp>::value &&
215945cacc8SJonathan Coe                                 is_constructible<_Tp, _Up&&>::value &&
216945cacc8SJonathan Coe                                 !__is_propagate_const<decay_t<_Up>>::value,bool> = true>
217945cacc8SJonathan Coe  explicit _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
218945cacc8SJonathan Coe      : __t_(std::forward<_Up>(__u))
219945cacc8SJonathan Coe  {
220945cacc8SJonathan Coe  }
221945cacc8SJonathan Coe
222945cacc8SJonathan Coe  template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
223945cacc8SJonathan Coe                                 is_constructible<_Tp, _Up&&>::value &&
224945cacc8SJonathan Coe                                 !__is_propagate_const<decay_t<_Up>>::value,bool> = false>
225945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
226945cacc8SJonathan Coe      : __t_(std::forward<_Up>(__u))
227945cacc8SJonathan Coe  {
228945cacc8SJonathan Coe  }
229945cacc8SJonathan Coe
230945cacc8SJonathan Coe  propagate_const& operator=(const propagate_const&) = delete;
231945cacc8SJonathan Coe
232945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default;
233945cacc8SJonathan Coe
234945cacc8SJonathan Coe  template <class _Up>
235945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu)
236945cacc8SJonathan Coe  {
237945cacc8SJonathan Coe    __t_ = std::move(_VSTD_LFTS_V2::get_underlying(__pu));
238945cacc8SJonathan Coe    return *this;
239945cacc8SJonathan Coe  }
240945cacc8SJonathan Coe
241945cacc8SJonathan Coe  template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>>
242945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR propagate_const& operator=(_Up&& __u)
243945cacc8SJonathan Coe  {
244945cacc8SJonathan Coe    __t_ = std::forward<_Up>(__u);
245945cacc8SJonathan Coe    return *this;
246945cacc8SJonathan Coe  }
247945cacc8SJonathan Coe
248945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR const element_type* get() const
249945cacc8SJonathan Coe  {
250945cacc8SJonathan Coe    return __get_pointer(__t_);
251945cacc8SJonathan Coe  }
252945cacc8SJonathan Coe
253945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR element_type* get()
254945cacc8SJonathan Coe  {
255945cacc8SJonathan Coe    return __get_pointer(__t_);
256945cacc8SJonathan Coe  }
257945cacc8SJonathan Coe
258945cacc8SJonathan Coe  explicit _LIBCPP_CONSTEXPR operator bool() const
259945cacc8SJonathan Coe  {
260945cacc8SJonathan Coe    return get() != nullptr;
261945cacc8SJonathan Coe  }
262945cacc8SJonathan Coe
263945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR const element_type* operator->() const
264945cacc8SJonathan Coe  {
265945cacc8SJonathan Coe    return get();
266945cacc8SJonathan Coe  }
267945cacc8SJonathan Coe
268945cacc8SJonathan Coe  template <class _Tp_ = _Tp, class _Up = enable_if_t<is_convertible<
269945cacc8SJonathan Coe                                  const _Tp_, const element_type *>::value>>
270945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR operator const element_type *() const {
271945cacc8SJonathan Coe    return get();
272945cacc8SJonathan Coe  }
273945cacc8SJonathan Coe
274945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR const element_type& operator*() const
275945cacc8SJonathan Coe  {
276945cacc8SJonathan Coe    return *get();
277945cacc8SJonathan Coe  }
278945cacc8SJonathan Coe
279945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR element_type* operator->()
280945cacc8SJonathan Coe  {
281945cacc8SJonathan Coe    return get();
282945cacc8SJonathan Coe  }
283945cacc8SJonathan Coe
284945cacc8SJonathan Coe  template <class _Tp_ = _Tp, class _Up = enable_if_t<
285945cacc8SJonathan Coe                                  is_convertible<_Tp_, element_type *>::value>>
286945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR operator element_type *() {
287945cacc8SJonathan Coe    return get();
288945cacc8SJonathan Coe  }
289945cacc8SJonathan Coe
290945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR element_type& operator*()
291945cacc8SJonathan Coe  {
292945cacc8SJonathan Coe    return *get();
293945cacc8SJonathan Coe  }
294945cacc8SJonathan Coe
295945cacc8SJonathan Coe  _LIBCPP_CONSTEXPR void swap(propagate_const& __pt) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
296945cacc8SJonathan Coe  {
297945cacc8SJonathan Coe    using _VSTD::swap;
298945cacc8SJonathan Coe    swap(__t_, __pt.__t_);
299945cacc8SJonathan Coe  }
300945cacc8SJonathan Coe};
301945cacc8SJonathan Coe
302945cacc8SJonathan Coe
303945cacc8SJonathan Coetemplate <class _Tp>
304945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
305945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, nullptr_t)
306945cacc8SJonathan Coe{
307945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) == nullptr;
308945cacc8SJonathan Coe}
309945cacc8SJonathan Coe
310945cacc8SJonathan Coetemplate <class _Tp>
311945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
312945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator==(nullptr_t, const propagate_const<_Tp>& __pt)
313945cacc8SJonathan Coe{
314945cacc8SJonathan Coe  return nullptr == _VSTD_LFTS_V2::get_underlying(__pt);
315945cacc8SJonathan Coe}
316945cacc8SJonathan Coe
317945cacc8SJonathan Coetemplate <class _Tp>
318945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
319945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
320945cacc8SJonathan Coe{
321945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) != nullptr;
322945cacc8SJonathan Coe}
323945cacc8SJonathan Coe
324945cacc8SJonathan Coetemplate <class _Tp>
325945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
326945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt)
327945cacc8SJonathan Coe{
328945cacc8SJonathan Coe  return nullptr != _VSTD_LFTS_V2::get_underlying(__pt);
329945cacc8SJonathan Coe}
330945cacc8SJonathan Coe
331945cacc8SJonathan Coetemplate <class _Tp, class _Up>
332945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
333945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt,
334945cacc8SJonathan Coe                          const propagate_const<_Up>& __pu)
335945cacc8SJonathan Coe{
336945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) == _VSTD_LFTS_V2::get_underlying(__pu);
337945cacc8SJonathan Coe}
338945cacc8SJonathan Coe
339945cacc8SJonathan Coetemplate <class _Tp, class _Up>
340945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
341945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt,
342945cacc8SJonathan Coe                          const propagate_const<_Up>& __pu)
343945cacc8SJonathan Coe{
344945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) != _VSTD_LFTS_V2::get_underlying(__pu);
345945cacc8SJonathan Coe}
346945cacc8SJonathan Coe
347945cacc8SJonathan Coetemplate <class _Tp, class _Up>
348945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
349945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt,
350945cacc8SJonathan Coe                         const propagate_const<_Up>& __pu)
351945cacc8SJonathan Coe{
352945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) < _VSTD_LFTS_V2::get_underlying(__pu);
353945cacc8SJonathan Coe}
354945cacc8SJonathan Coe
355945cacc8SJonathan Coetemplate <class _Tp, class _Up>
356945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
357945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt,
358945cacc8SJonathan Coe                         const propagate_const<_Up>& __pu)
359945cacc8SJonathan Coe{
360945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) > _VSTD_LFTS_V2::get_underlying(__pu);
361945cacc8SJonathan Coe}
362945cacc8SJonathan Coe
363945cacc8SJonathan Coetemplate <class _Tp, class _Up>
364945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
365945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt,
366945cacc8SJonathan Coe                          const propagate_const<_Up>& __pu)
367945cacc8SJonathan Coe{
368945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) <= _VSTD_LFTS_V2::get_underlying(__pu);
369945cacc8SJonathan Coe}
370945cacc8SJonathan Coe
371945cacc8SJonathan Coetemplate <class _Tp, class _Up>
372945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
373945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt,
374945cacc8SJonathan Coe                          const propagate_const<_Up>& __pu)
375945cacc8SJonathan Coe{
376945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) >= _VSTD_LFTS_V2::get_underlying(__pu);
377945cacc8SJonathan Coe}
378945cacc8SJonathan Coe
379945cacc8SJonathan Coetemplate <class _Tp, class _Up>
380945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
381945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
382945cacc8SJonathan Coe{
383945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) == __u;
384945cacc8SJonathan Coe}
385945cacc8SJonathan Coe
386945cacc8SJonathan Coetemplate <class _Tp, class _Up>
387945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
388945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
389945cacc8SJonathan Coe{
390945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) != __u;
391945cacc8SJonathan Coe}
392945cacc8SJonathan Coe
393945cacc8SJonathan Coetemplate <class _Tp, class _Up>
394945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
395945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
396945cacc8SJonathan Coe{
397945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) < __u;
398945cacc8SJonathan Coe}
399945cacc8SJonathan Coe
400945cacc8SJonathan Coetemplate <class _Tp, class _Up>
401945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
402945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
403945cacc8SJonathan Coe{
404945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) > __u;
405945cacc8SJonathan Coe}
406945cacc8SJonathan Coe
407945cacc8SJonathan Coetemplate <class _Tp, class _Up>
408945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
409945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
410945cacc8SJonathan Coe{
411945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) <= __u;
412945cacc8SJonathan Coe}
413945cacc8SJonathan Coe
414945cacc8SJonathan Coetemplate <class _Tp, class _Up>
415945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
416945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
417945cacc8SJonathan Coe{
418945cacc8SJonathan Coe  return _VSTD_LFTS_V2::get_underlying(__pt) >= __u;
419945cacc8SJonathan Coe}
420945cacc8SJonathan Coe
421945cacc8SJonathan Coe
422945cacc8SJonathan Coetemplate <class _Tp, class _Up>
423945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
424945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
425945cacc8SJonathan Coe{
426945cacc8SJonathan Coe  return __t == _VSTD_LFTS_V2::get_underlying(__pu);
427945cacc8SJonathan Coe}
428945cacc8SJonathan Coe
429945cacc8SJonathan Coetemplate <class _Tp, class _Up>
430945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
431945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
432945cacc8SJonathan Coe{
433945cacc8SJonathan Coe  return __t != _VSTD_LFTS_V2::get_underlying(__pu);
434945cacc8SJonathan Coe}
435945cacc8SJonathan Coe
436945cacc8SJonathan Coetemplate <class _Tp, class _Up>
437945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
438945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
439945cacc8SJonathan Coe{
440945cacc8SJonathan Coe  return __t < _VSTD_LFTS_V2::get_underlying(__pu);
441945cacc8SJonathan Coe}
442945cacc8SJonathan Coe
443945cacc8SJonathan Coetemplate <class _Tp, class _Up>
444945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
445945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
446945cacc8SJonathan Coe{
447945cacc8SJonathan Coe  return __t > _VSTD_LFTS_V2::get_underlying(__pu);
448945cacc8SJonathan Coe}
449945cacc8SJonathan Coe
450945cacc8SJonathan Coetemplate <class _Tp, class _Up>
451945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
452945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
453945cacc8SJonathan Coe{
454945cacc8SJonathan Coe  return __t <= _VSTD_LFTS_V2::get_underlying(__pu);
455945cacc8SJonathan Coe}
456945cacc8SJonathan Coe
457945cacc8SJonathan Coetemplate <class _Tp, class _Up>
458945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
459945cacc8SJonathan Coe_LIBCPP_CONSTEXPR bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
460945cacc8SJonathan Coe{
461945cacc8SJonathan Coe  return __t >= _VSTD_LFTS_V2::get_underlying(__pu);
462945cacc8SJonathan Coe}
463945cacc8SJonathan Coe
464945cacc8SJonathan Coetemplate <class _Tp>
465945cacc8SJonathan Coe_LIBCPP_INLINE_VISIBILITY
466945cacc8SJonathan Coe_LIBCPP_CONSTEXPR void swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
467945cacc8SJonathan Coe{
4686d1aec12SMarshall Clow  __pc1.swap(__pc2);
469945cacc8SJonathan Coe}
470945cacc8SJonathan Coe
471945cacc8SJonathan Coetemplate <class _Tp>
472945cacc8SJonathan Coe_LIBCPP_CONSTEXPR const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT
473945cacc8SJonathan Coe{
474945cacc8SJonathan Coe  return __pt.__t_;
475945cacc8SJonathan Coe}
476945cacc8SJonathan Coe
477945cacc8SJonathan Coetemplate <class _Tp>
478945cacc8SJonathan Coe_LIBCPP_CONSTEXPR _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT
479945cacc8SJonathan Coe{
480945cacc8SJonathan Coe  return __pt.__t_;
481945cacc8SJonathan Coe}
482945cacc8SJonathan Coe
483945cacc8SJonathan Coe_LIBCPP_END_NAMESPACE_LFTS_V2
484945cacc8SJonathan Coe
485945cacc8SJonathan Coe_LIBCPP_BEGIN_NAMESPACE_STD
486945cacc8SJonathan Coe
487945cacc8SJonathan Coetemplate <class _Tp>
488945cacc8SJonathan Coestruct hash<experimental::fundamentals_v2::propagate_const<_Tp>>
489945cacc8SJonathan Coe{
490945cacc8SJonathan Coe  typedef size_t result_type;
491945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> argument_type;
492945cacc8SJonathan Coe
493945cacc8SJonathan Coe  size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const
494945cacc8SJonathan Coe  {
495945cacc8SJonathan Coe    return std::hash<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1));
496945cacc8SJonathan Coe  }
497945cacc8SJonathan Coe};
498945cacc8SJonathan Coe
499945cacc8SJonathan Coetemplate <class _Tp>
500945cacc8SJonathan Coestruct equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
501945cacc8SJonathan Coe{
502945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
503945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
504945cacc8SJonathan Coe
505945cacc8SJonathan Coe  bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
506945cacc8SJonathan Coe      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
507945cacc8SJonathan Coe  {
508945cacc8SJonathan Coe    return std::equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
509945cacc8SJonathan Coe  }
510945cacc8SJonathan Coe};
511945cacc8SJonathan Coe
512945cacc8SJonathan Coetemplate <class _Tp>
513945cacc8SJonathan Coestruct not_equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
514945cacc8SJonathan Coe{
515945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
516945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
517945cacc8SJonathan Coe
518945cacc8SJonathan Coe  bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
519945cacc8SJonathan Coe      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
520945cacc8SJonathan Coe  {
521945cacc8SJonathan Coe    return std::not_equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
522945cacc8SJonathan Coe  }
523945cacc8SJonathan Coe};
524945cacc8SJonathan Coe
525945cacc8SJonathan Coetemplate <class _Tp>
526945cacc8SJonathan Coestruct less<experimental::fundamentals_v2::propagate_const<_Tp>>
527945cacc8SJonathan Coe{
528945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
529945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
530945cacc8SJonathan Coe
531945cacc8SJonathan Coe  bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
532945cacc8SJonathan Coe      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
533945cacc8SJonathan Coe  {
534945cacc8SJonathan Coe    return std::less<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
535945cacc8SJonathan Coe  }
536945cacc8SJonathan Coe};
537945cacc8SJonathan Coe
538945cacc8SJonathan Coetemplate <class _Tp>
539945cacc8SJonathan Coestruct greater<experimental::fundamentals_v2::propagate_const<_Tp>>
540945cacc8SJonathan Coe{
541945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
542945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
543945cacc8SJonathan Coe
544945cacc8SJonathan Coe  bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
545945cacc8SJonathan Coe      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
546945cacc8SJonathan Coe  {
547945cacc8SJonathan Coe    return std::greater<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
548945cacc8SJonathan Coe  }
549945cacc8SJonathan Coe};
550945cacc8SJonathan Coe
551945cacc8SJonathan Coetemplate <class _Tp>
552945cacc8SJonathan Coestruct less_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
553945cacc8SJonathan Coe{
554945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
555945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
556945cacc8SJonathan Coe
557945cacc8SJonathan Coe  bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
558945cacc8SJonathan Coe      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
559945cacc8SJonathan Coe  {
560945cacc8SJonathan Coe    return std::less_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
561945cacc8SJonathan Coe  }
562945cacc8SJonathan Coe};
563945cacc8SJonathan Coe
564945cacc8SJonathan Coetemplate <class _Tp>
565945cacc8SJonathan Coestruct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
566945cacc8SJonathan Coe{
567945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
568945cacc8SJonathan Coe  typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
569945cacc8SJonathan Coe
570945cacc8SJonathan Coe  bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
571945cacc8SJonathan Coe      const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
572945cacc8SJonathan Coe  {
573945cacc8SJonathan Coe    return std::greater_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
574945cacc8SJonathan Coe  }
575945cacc8SJonathan Coe};
576945cacc8SJonathan Coe
577945cacc8SJonathan Coe_LIBCPP_END_NAMESPACE_STD
578945cacc8SJonathan Coe
579945cacc8SJonathan Coe#endif // _LIBCPP_STD_VER > 11
580945cacc8SJonathan Coe#endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
581