2 //===------------------------ propagate_const -----------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
11 #define _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
13 propagate_const synopsis
15 namespace std { namespace experimental { inline namespace fundamentals_v2 {
18 template <class T> class propagate_const;
20 // [propagate_const.underlying], underlying pointer access
21 constexpr const _Tp& _VSTD_LFTS_V2::get_underlying(const propagate_const<T>& pt) noexcept;
22 constexpr T& _VSTD_LFTS_V2::get_underlying(propagate_const<T>& pt) noexcept;
24 // [propagate_const.relational], relational operators
25 template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
26 template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);
27 template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
28 template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& pu);
29 template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
30 template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
31 template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
32 template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
33 template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
34 template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const propagate_const<_Up>& pu);
35 template <class T, class U> constexpr bool operator==(const propagate_const<T>& pt, const _Up& u);
36 template <class T, class U> constexpr bool operator!=(const propagate_const<T>& pt, const _Up& u);
37 template <class T, class U> constexpr bool operator<(const propagate_const<T>& pt, const _Up& u);
38 template <class T, class U> constexpr bool operator>(const propagate_const<T>& pt, const _Up& u);
39 template <class T, class U> constexpr bool operator<=(const propagate_const<T>& pt, const _Up& u);
40 template <class T, class U> constexpr bool operator>=(const propagate_const<T>& pt, const _Up& u);
41 template <class T, class U> constexpr bool operator==(const _Tp& t, const propagate_const<_Up>& pu);
42 template <class T, class U> constexpr bool operator!=(const _Tp& t, const propagate_const<_Up>& pu);
43 template <class T, class U> constexpr bool operator<(const _Tp& t, const propagate_const<_Up>& pu);
44 template <class T, class U> constexpr bool operator>(const _Tp& t, const propagate_const<_Up>& pu);
45 template <class T, class U> constexpr bool operator<=(const _Tp& t, const propagate_const<_Up>& pu);
46 template <class T, class U> constexpr bool operator>=(const _Tp& t, const propagate_const<_Up>& pu);
48 // [propagate_const.algorithms], specialized algorithms
49 template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below);
56 typedef remove_reference_t<decltype(*declval<T&>())> element_type;
58 // [propagate_const.ctor], constructors
59 constexpr propagate_const() = default;
60 propagate_const(const propagate_const& p) = delete;
61 constexpr propagate_const(propagate_const&& p) = default;
62 template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below
63 template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below
65 // [propagate_const.assignment], assignment
66 propagate_const& operator=(const propagate_const& p) = delete;
67 constexpr propagate_const& operator=(propagate_const&& p) = default;
68 template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu);
69 template <class U> constexpr propagate_const& operator=(U&& u); // see below
71 // [propagate_const.const_observers], const observers
72 explicit constexpr operator bool() const;
73 constexpr const element_type* operator->() const;
74 constexpr operator const element_type*() const; // Not always defined
75 constexpr const element_type& operator*() const;
76 constexpr const element_type* get() const;
78 // [propagate_const.non_const_observers], non-const observers
79 constexpr element_type* operator->();
80 constexpr operator element_type*(); // Not always defined
81 constexpr element_type& operator*();
82 constexpr element_type* get();
84 // [propagate_const.modifiers], modifiers
85 constexpr void swap(propagate_const& pt) noexcept(see below)
88 T t_; // exposition only
91 } // namespace fundamentals_v2
92 } // namespace experimental
94 // [propagate_const.hash], hash support
95 template <class T> struct hash<experimental::fundamentals_v2::propagate_const<T>>;
97 // [propagate_const.comparison_function_objects], comparison function objects
98 template <class T> struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;
99 template <class T> struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;
100 template <class T> struct less<experimental::fundamentals_v2::propagate_const<T>>;
101 template <class T> struct greater<experimental::fundamentals_v2::propagate_const<T>>;
102 template <class T> struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;
103 template <class T> struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;
109 #include <experimental/__config>
110 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
111 #pragma GCC system_header
114 #if _LIBCPP_STD_VER > 11
116 #include <type_traits>
118 #include <functional>
120 _LIBCPP_BEGIN_NAMESPACE_LFTS_V2
124 class propagate_const;
127 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
128 const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
131 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
132 _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
135 class propagate_const
138 typedef remove_reference_t<decltype(*_VSTD::declval<_Tp&>())> element_type;
140 static_assert(!is_array<_Tp>::value,
141 "Instantiation of propagate_const with an array type is ill-formed.");
142 static_assert(!is_reference<_Tp>::value,
143 "Instantiation of propagate_const with a reference type is ill-formed.");
144 static_assert(!(is_pointer<_Tp>::value && is_function<typename remove_pointer<_Tp>::type>::value),
145 "Instantiation of propagate_const with a function-pointer type is ill-formed.");
146 static_assert(!(is_pointer<_Tp>::value && is_same<typename remove_cv<typename remove_pointer<_Tp>::type>::type, void>::value),
147 "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
151 static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u)
157 static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u)
159 return __get_pointer(__u.get());
163 static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u)
169 static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u)
171 return __get_pointer(__u.get());
175 struct __is_propagate_const : false_type
180 struct __is_propagate_const<propagate_const<_Up>> : true_type
188 template <class _Up> friend _LIBCPP_CONSTEXPR const _Up& ::_VSTD_LFTS_V2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
189 template <class _Up> friend _LIBCPP_CONSTEXPR _Up& ::_VSTD_LFTS_V2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
191 _LIBCPP_CONSTEXPR propagate_const() = default;
193 propagate_const(const propagate_const&) = delete;
195 _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default;
197 template <class _Up, enable_if_t<!is_convertible<_Up, _Tp>::value &&
198 is_constructible<_Tp, _Up&&>::value,bool> = true>
199 explicit _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
200 : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
204 template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
205 is_constructible<_Tp, _Up&&>::value,bool> = false>
206 _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
207 : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
211 template <class _Up, enable_if_t<!is_convertible<_Up&&, _Tp>::value &&
212 is_constructible<_Tp, _Up&&>::value &&
213 !__is_propagate_const<decay_t<_Up>>::value,bool> = true>
214 explicit _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
215 : __t_(std::forward<_Up>(__u))
219 template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
220 is_constructible<_Tp, _Up&&>::value &&
221 !__is_propagate_const<decay_t<_Up>>::value,bool> = false>
222 _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
223 : __t_(std::forward<_Up>(__u))
227 propagate_const& operator=(const propagate_const&) = delete;
229 _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default;
232 _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu)
234 __t_ = std::move(_VSTD_LFTS_V2::get_underlying(__pu));
238 template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>>
239 _LIBCPP_CONSTEXPR propagate_const& operator=(_Up&& __u)
241 __t_ = std::forward<_Up>(__u);
245 _LIBCPP_CONSTEXPR const element_type* get() const
247 return __get_pointer(__t_);
250 _LIBCPP_CONSTEXPR element_type* get()
252 return __get_pointer(__t_);
255 explicit _LIBCPP_CONSTEXPR operator bool() const
257 return get() != nullptr;
260 _LIBCPP_CONSTEXPR const element_type* operator->() const
265 template <class _Tp_ = _Tp, class _Up = enable_if_t<is_convertible<
266 const _Tp_, const element_type *>::value>>
267 _LIBCPP_CONSTEXPR operator const element_type *() const {
271 _LIBCPP_CONSTEXPR const element_type& operator*() const
276 _LIBCPP_CONSTEXPR element_type* operator->()
281 template <class _Tp_ = _Tp, class _Up = enable_if_t<
282 is_convertible<_Tp_, element_type *>::value>>
283 _LIBCPP_CONSTEXPR operator element_type *() {
287 _LIBCPP_CONSTEXPR element_type& operator*()
292 _LIBCPP_CONSTEXPR void swap(propagate_const& __pt) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
295 swap(__t_, __pt.__t_);
301 _LIBCPP_INLINE_VISIBILITY
302 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, nullptr_t)
304 return _VSTD_LFTS_V2::get_underlying(__pt) == nullptr;
308 _LIBCPP_INLINE_VISIBILITY
309 _LIBCPP_CONSTEXPR bool operator==(nullptr_t, const propagate_const<_Tp>& __pt)
311 return nullptr == _VSTD_LFTS_V2::get_underlying(__pt);
315 _LIBCPP_INLINE_VISIBILITY
316 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
318 return _VSTD_LFTS_V2::get_underlying(__pt) != nullptr;
322 _LIBCPP_INLINE_VISIBILITY
323 _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt)
325 return nullptr != _VSTD_LFTS_V2::get_underlying(__pt);
328 template <class _Tp, class _Up>
329 _LIBCPP_INLINE_VISIBILITY
330 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt,
331 const propagate_const<_Up>& __pu)
333 return _VSTD_LFTS_V2::get_underlying(__pt) == _VSTD_LFTS_V2::get_underlying(__pu);
336 template <class _Tp, class _Up>
337 _LIBCPP_INLINE_VISIBILITY
338 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt,
339 const propagate_const<_Up>& __pu)
341 return _VSTD_LFTS_V2::get_underlying(__pt) != _VSTD_LFTS_V2::get_underlying(__pu);
344 template <class _Tp, class _Up>
345 _LIBCPP_INLINE_VISIBILITY
346 _LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt,
347 const propagate_const<_Up>& __pu)
349 return _VSTD_LFTS_V2::get_underlying(__pt) < _VSTD_LFTS_V2::get_underlying(__pu);
352 template <class _Tp, class _Up>
353 _LIBCPP_INLINE_VISIBILITY
354 _LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt,
355 const propagate_const<_Up>& __pu)
357 return _VSTD_LFTS_V2::get_underlying(__pt) > _VSTD_LFTS_V2::get_underlying(__pu);
360 template <class _Tp, class _Up>
361 _LIBCPP_INLINE_VISIBILITY
362 _LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt,
363 const propagate_const<_Up>& __pu)
365 return _VSTD_LFTS_V2::get_underlying(__pt) <= _VSTD_LFTS_V2::get_underlying(__pu);
368 template <class _Tp, class _Up>
369 _LIBCPP_INLINE_VISIBILITY
370 _LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt,
371 const propagate_const<_Up>& __pu)
373 return _VSTD_LFTS_V2::get_underlying(__pt) >= _VSTD_LFTS_V2::get_underlying(__pu);
376 template <class _Tp, class _Up>
377 _LIBCPP_INLINE_VISIBILITY
378 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
380 return _VSTD_LFTS_V2::get_underlying(__pt) == __u;
383 template <class _Tp, class _Up>
384 _LIBCPP_INLINE_VISIBILITY
385 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
387 return _VSTD_LFTS_V2::get_underlying(__pt) != __u;
390 template <class _Tp, class _Up>
391 _LIBCPP_INLINE_VISIBILITY
392 _LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
394 return _VSTD_LFTS_V2::get_underlying(__pt) < __u;
397 template <class _Tp, class _Up>
398 _LIBCPP_INLINE_VISIBILITY
399 _LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
401 return _VSTD_LFTS_V2::get_underlying(__pt) > __u;
404 template <class _Tp, class _Up>
405 _LIBCPP_INLINE_VISIBILITY
406 _LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
408 return _VSTD_LFTS_V2::get_underlying(__pt) <= __u;
411 template <class _Tp, class _Up>
412 _LIBCPP_INLINE_VISIBILITY
413 _LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
415 return _VSTD_LFTS_V2::get_underlying(__pt) >= __u;
419 template <class _Tp, class _Up>
420 _LIBCPP_INLINE_VISIBILITY
421 _LIBCPP_CONSTEXPR bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
423 return __t == _VSTD_LFTS_V2::get_underlying(__pu);
426 template <class _Tp, class _Up>
427 _LIBCPP_INLINE_VISIBILITY
428 _LIBCPP_CONSTEXPR bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
430 return __t != _VSTD_LFTS_V2::get_underlying(__pu);
433 template <class _Tp, class _Up>
434 _LIBCPP_INLINE_VISIBILITY
435 _LIBCPP_CONSTEXPR bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
437 return __t < _VSTD_LFTS_V2::get_underlying(__pu);
440 template <class _Tp, class _Up>
441 _LIBCPP_INLINE_VISIBILITY
442 _LIBCPP_CONSTEXPR bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
444 return __t > _VSTD_LFTS_V2::get_underlying(__pu);
447 template <class _Tp, class _Up>
448 _LIBCPP_INLINE_VISIBILITY
449 _LIBCPP_CONSTEXPR bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
451 return __t <= _VSTD_LFTS_V2::get_underlying(__pu);
454 template <class _Tp, class _Up>
455 _LIBCPP_INLINE_VISIBILITY
456 _LIBCPP_CONSTEXPR bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
458 return __t >= _VSTD_LFTS_V2::get_underlying(__pu);
462 _LIBCPP_INLINE_VISIBILITY
463 _LIBCPP_CONSTEXPR void swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
469 _LIBCPP_CONSTEXPR const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT
475 _LIBCPP_CONSTEXPR _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT
480 _LIBCPP_END_NAMESPACE_LFTS_V2
482 _LIBCPP_BEGIN_NAMESPACE_STD
485 struct hash<experimental::fundamentals_v2::propagate_const<_Tp>>
487 typedef size_t result_type;
488 typedef experimental::fundamentals_v2::propagate_const<_Tp> argument_type;
490 size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const
492 return std::hash<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1));
497 struct equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
499 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
500 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
502 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
503 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
505 return std::equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
510 struct not_equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
512 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
513 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
515 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
516 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
518 return std::not_equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
523 struct less<experimental::fundamentals_v2::propagate_const<_Tp>>
525 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
526 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
528 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
529 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
531 return std::less<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
536 struct greater<experimental::fundamentals_v2::propagate_const<_Tp>>
538 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
539 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
541 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
542 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
544 return std::greater<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
549 struct less_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
551 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
552 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
554 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
555 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
557 return std::less_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
562 struct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
564 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
565 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
567 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
568 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
570 return std::greater_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
574 _LIBCPP_END_NAMESPACE_STD
576 #endif // _LIBCPP_STD_VER > 11
577 #endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST