2 //===------------------------ propagate_const -----------------------------===//
4 // The LLVM Compiler Infrastructure
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 #ifndef _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
12 #define _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST
14 propagate_const synopsis
16 namespace std { namespace experimental { inline namespace fundamentals_v2 {
19 template <class T> class propagate_const;
21 // [propagate_const.underlying], underlying pointer access
22 constexpr const _Tp& _VSTD_LFTS_V2::get_underlying(const propagate_const<T>& pt) noexcept;
23 constexpr T& _VSTD_LFTS_V2::get_underlying(propagate_const<T>& pt) noexcept;
25 // [propagate_const.relational], relational operators
26 template <class T> constexpr bool operator==(const propagate_const<T>& pt, nullptr_t);
27 template <class T> constexpr bool operator==(nullptr_t, const propagate_const<T>& pu);
28 template <class T> constexpr bool operator!=(const propagate_const<T>& pt, nullptr_t);
29 template <class T> constexpr bool operator!=(nullptr_t, const propagate_const<T>& 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 propagate_const<_Up>& pu);
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 propagate_const<T>& pt, const _Up& u);
42 template <class T, class U> constexpr bool operator==(const _Tp& t, const propagate_const<_Up>& pu);
43 template <class T, class U> constexpr bool operator!=(const _Tp& t, const propagate_const<_Up>& pu);
44 template <class T, class U> constexpr bool operator<(const _Tp& t, const propagate_const<_Up>& pu);
45 template <class T, class U> constexpr bool operator>(const _Tp& t, const propagate_const<_Up>& pu);
46 template <class T, class U> constexpr bool operator<=(const _Tp& t, const propagate_const<_Up>& pu);
47 template <class T, class U> constexpr bool operator>=(const _Tp& t, const propagate_const<_Up>& pu);
49 // [propagate_const.algorithms], specialized algorithms
50 template <class T> constexpr void swap(propagate_const<T>& pt, propagate_const<T>& pu) noexcept(see below);
57 typedef remove_reference_t<decltype(*declval<T&>())> element_type;
59 // [propagate_const.ctor], constructors
60 constexpr propagate_const() = default;
61 propagate_const(const propagate_const& p) = delete;
62 constexpr propagate_const(propagate_const&& p) = default;
63 template <class U> EXPLICIT constexpr propagate_const(propagate_const<_Up>&& pu); // see below
64 template <class U> EXPLICIT constexpr propagate_const(U&& u); // see below
66 // [propagate_const.assignment], assignment
67 propagate_const& operator=(const propagate_const& p) = delete;
68 constexpr propagate_const& operator=(propagate_const&& p) = default;
69 template <class U> constexpr propagate_const& operator=(propagate_const<_Up>&& pu);
70 template <class U> constexpr propagate_const& operator=(U&& u); // see below
72 // [propagate_const.const_observers], const observers
73 explicit constexpr operator bool() const;
74 constexpr const element_type* operator->() const;
75 constexpr operator const element_type*() const; // Not always defined
76 constexpr const element_type& operator*() const;
77 constexpr const element_type* get() const;
79 // [propagate_const.non_const_observers], non-const observers
80 constexpr element_type* operator->();
81 constexpr operator element_type*(); // Not always defined
82 constexpr element_type& operator*();
83 constexpr element_type* get();
85 // [propagate_const.modifiers], modifiers
86 constexpr void swap(propagate_const& pt) noexcept(see below)
89 T t_; // exposition only
92 } // namespace fundamentals_v2
93 } // namespace experimental
95 // [propagate_const.hash], hash support
96 template <class T> struct hash<experimental::fundamentals_v2::propagate_const<T>>;
98 // [propagate_const.comparison_function_objects], comparison function objects
99 template <class T> struct equal_to<experimental::fundamentals_v2::propagate_const<T>>;
100 template <class T> struct not_equal_to<experimental::fundamentals_v2::propagate_const<T>>;
101 template <class T> struct less<experimental::fundamentals_v2::propagate_const<T>>;
102 template <class T> struct greater<experimental::fundamentals_v2::propagate_const<T>>;
103 template <class T> struct less_equal<experimental::fundamentals_v2::propagate_const<T>>;
104 template <class T> struct greater_equal<experimental::fundamentals_v2::propagate_const<T>>;
110 #include <experimental/__config>
111 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
112 #pragma GCC system_header
115 #if _LIBCPP_STD_VER > 11
117 #include <type_traits>
119 #include <functional>
121 _LIBCPP_BEGIN_NAMESPACE_LFTS_V2
125 class propagate_const;
128 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
129 const _Up& get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
132 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
133 _Up& get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
136 class propagate_const
139 typedef remove_reference_t<decltype(*_VSTD::declval<_Tp&>())> element_type;
141 static_assert(!is_array<_Tp>::value,
142 "Instantiation of propagate_const with an array type is ill-formed.");
143 static_assert(!is_reference<_Tp>::value,
144 "Instantiation of propagate_const with a reference type is ill-formed.");
145 static_assert(!(is_pointer<_Tp>::value && is_function<typename remove_pointer<_Tp>::type>::value),
146 "Instantiation of propagate_const with a function-pointer type is ill-formed.");
147 static_assert(!(is_pointer<_Tp>::value && is_same<typename remove_cv<typename remove_pointer<_Tp>::type>::type, void>::value),
148 "Instantiation of propagate_const with a pointer to (possibly cv-qualified) void is ill-formed.");
152 static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up* __u)
158 static _LIBCPP_CONSTEXPR element_type* __get_pointer(_Up& __u)
160 return __get_pointer(__u.get());
164 static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up* __u)
170 static _LIBCPP_CONSTEXPR const element_type* __get_pointer(const _Up& __u)
172 return __get_pointer(__u.get());
176 struct __is_propagate_const : false_type
181 struct __is_propagate_const<propagate_const<_Up>> : true_type
189 template <class _Up> friend _LIBCPP_CONSTEXPR const _Up& ::_VSTD_LFTS_V2::get_underlying(const propagate_const<_Up>& __pu) _NOEXCEPT;
190 template <class _Up> friend _LIBCPP_CONSTEXPR _Up& ::_VSTD_LFTS_V2::get_underlying(propagate_const<_Up>& __pu) _NOEXCEPT;
192 _LIBCPP_CONSTEXPR propagate_const() = default;
194 propagate_const(const propagate_const&) = delete;
196 _LIBCPP_CONSTEXPR propagate_const(propagate_const&&) = default;
198 template <class _Up, enable_if_t<!is_convertible<_Up, _Tp>::value &&
199 is_constructible<_Tp, _Up&&>::value,bool> = true>
200 explicit _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
201 : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
205 template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
206 is_constructible<_Tp, _Up&&>::value,bool> = false>
207 _LIBCPP_CONSTEXPR propagate_const(propagate_const<_Up>&& __pu)
208 : __t_(std::move(_VSTD_LFTS_V2::get_underlying(__pu)))
212 template <class _Up, enable_if_t<!is_convertible<_Up&&, _Tp>::value &&
213 is_constructible<_Tp, _Up&&>::value &&
214 !__is_propagate_const<decay_t<_Up>>::value,bool> = true>
215 explicit _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
216 : __t_(std::forward<_Up>(__u))
220 template <class _Up, enable_if_t<is_convertible<_Up&&, _Tp>::value &&
221 is_constructible<_Tp, _Up&&>::value &&
222 !__is_propagate_const<decay_t<_Up>>::value,bool> = false>
223 _LIBCPP_CONSTEXPR propagate_const(_Up&& __u)
224 : __t_(std::forward<_Up>(__u))
228 propagate_const& operator=(const propagate_const&) = delete;
230 _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const&&) = default;
233 _LIBCPP_CONSTEXPR propagate_const& operator=(propagate_const<_Up>&& __pu)
235 __t_ = std::move(_VSTD_LFTS_V2::get_underlying(__pu));
239 template <class _Up, class _Vp = enable_if_t<!__is_propagate_const<decay_t<_Up>>::value>>
240 _LIBCPP_CONSTEXPR propagate_const& operator=(_Up&& __u)
242 __t_ = std::forward<_Up>(__u);
246 _LIBCPP_CONSTEXPR const element_type* get() const
248 return __get_pointer(__t_);
251 _LIBCPP_CONSTEXPR element_type* get()
253 return __get_pointer(__t_);
256 explicit _LIBCPP_CONSTEXPR operator bool() const
258 return get() != nullptr;
261 _LIBCPP_CONSTEXPR const element_type* operator->() const
266 template <class _Tp_ = _Tp, class _Up = enable_if_t<is_convertible<
267 const _Tp_, const element_type *>::value>>
268 _LIBCPP_CONSTEXPR operator const element_type *() const {
272 _LIBCPP_CONSTEXPR const element_type& operator*() const
277 _LIBCPP_CONSTEXPR element_type* operator->()
282 template <class _Tp_ = _Tp, class _Up = enable_if_t<
283 is_convertible<_Tp_, element_type *>::value>>
284 _LIBCPP_CONSTEXPR operator element_type *() {
288 _LIBCPP_CONSTEXPR element_type& operator*()
293 _LIBCPP_CONSTEXPR void swap(propagate_const& __pt) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
296 swap(__t_, __pt.__t_);
302 _LIBCPP_INLINE_VISIBILITY
303 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, nullptr_t)
305 return _VSTD_LFTS_V2::get_underlying(__pt) == nullptr;
309 _LIBCPP_INLINE_VISIBILITY
310 _LIBCPP_CONSTEXPR bool operator==(nullptr_t, const propagate_const<_Tp>& __pt)
312 return nullptr == _VSTD_LFTS_V2::get_underlying(__pt);
316 _LIBCPP_INLINE_VISIBILITY
317 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
319 return _VSTD_LFTS_V2::get_underlying(__pt) != nullptr;
323 _LIBCPP_INLINE_VISIBILITY
324 _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, const propagate_const<_Tp>& __pt)
326 return nullptr != _VSTD_LFTS_V2::get_underlying(__pt);
329 template <class _Tp, class _Up>
330 _LIBCPP_INLINE_VISIBILITY
331 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt,
332 const propagate_const<_Up>& __pu)
334 return _VSTD_LFTS_V2::get_underlying(__pt) == _VSTD_LFTS_V2::get_underlying(__pu);
337 template <class _Tp, class _Up>
338 _LIBCPP_INLINE_VISIBILITY
339 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt,
340 const propagate_const<_Up>& __pu)
342 return _VSTD_LFTS_V2::get_underlying(__pt) != _VSTD_LFTS_V2::get_underlying(__pu);
345 template <class _Tp, class _Up>
346 _LIBCPP_INLINE_VISIBILITY
347 _LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt,
348 const propagate_const<_Up>& __pu)
350 return _VSTD_LFTS_V2::get_underlying(__pt) < _VSTD_LFTS_V2::get_underlying(__pu);
353 template <class _Tp, class _Up>
354 _LIBCPP_INLINE_VISIBILITY
355 _LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt,
356 const propagate_const<_Up>& __pu)
358 return _VSTD_LFTS_V2::get_underlying(__pt) > _VSTD_LFTS_V2::get_underlying(__pu);
361 template <class _Tp, class _Up>
362 _LIBCPP_INLINE_VISIBILITY
363 _LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt,
364 const propagate_const<_Up>& __pu)
366 return _VSTD_LFTS_V2::get_underlying(__pt) <= _VSTD_LFTS_V2::get_underlying(__pu);
369 template <class _Tp, class _Up>
370 _LIBCPP_INLINE_VISIBILITY
371 _LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt,
372 const propagate_const<_Up>& __pu)
374 return _VSTD_LFTS_V2::get_underlying(__pt) >= _VSTD_LFTS_V2::get_underlying(__pu);
377 template <class _Tp, class _Up>
378 _LIBCPP_INLINE_VISIBILITY
379 _LIBCPP_CONSTEXPR bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
381 return _VSTD_LFTS_V2::get_underlying(__pt) == __u;
384 template <class _Tp, class _Up>
385 _LIBCPP_INLINE_VISIBILITY
386 _LIBCPP_CONSTEXPR bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
388 return _VSTD_LFTS_V2::get_underlying(__pt) != __u;
391 template <class _Tp, class _Up>
392 _LIBCPP_INLINE_VISIBILITY
393 _LIBCPP_CONSTEXPR bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
395 return _VSTD_LFTS_V2::get_underlying(__pt) < __u;
398 template <class _Tp, class _Up>
399 _LIBCPP_INLINE_VISIBILITY
400 _LIBCPP_CONSTEXPR bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
402 return _VSTD_LFTS_V2::get_underlying(__pt) > __u;
405 template <class _Tp, class _Up>
406 _LIBCPP_INLINE_VISIBILITY
407 _LIBCPP_CONSTEXPR bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
409 return _VSTD_LFTS_V2::get_underlying(__pt) <= __u;
412 template <class _Tp, class _Up>
413 _LIBCPP_INLINE_VISIBILITY
414 _LIBCPP_CONSTEXPR bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
416 return _VSTD_LFTS_V2::get_underlying(__pt) >= __u;
420 template <class _Tp, class _Up>
421 _LIBCPP_INLINE_VISIBILITY
422 _LIBCPP_CONSTEXPR bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
424 return __t == _VSTD_LFTS_V2::get_underlying(__pu);
427 template <class _Tp, class _Up>
428 _LIBCPP_INLINE_VISIBILITY
429 _LIBCPP_CONSTEXPR bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
431 return __t != _VSTD_LFTS_V2::get_underlying(__pu);
434 template <class _Tp, class _Up>
435 _LIBCPP_INLINE_VISIBILITY
436 _LIBCPP_CONSTEXPR bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
438 return __t < _VSTD_LFTS_V2::get_underlying(__pu);
441 template <class _Tp, class _Up>
442 _LIBCPP_INLINE_VISIBILITY
443 _LIBCPP_CONSTEXPR bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
445 return __t > _VSTD_LFTS_V2::get_underlying(__pu);
448 template <class _Tp, class _Up>
449 _LIBCPP_INLINE_VISIBILITY
450 _LIBCPP_CONSTEXPR bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
452 return __t <= _VSTD_LFTS_V2::get_underlying(__pu);
455 template <class _Tp, class _Up>
456 _LIBCPP_INLINE_VISIBILITY
457 _LIBCPP_CONSTEXPR bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
459 return __t >= _VSTD_LFTS_V2::get_underlying(__pu);
463 _LIBCPP_INLINE_VISIBILITY
464 _LIBCPP_CONSTEXPR void swap(propagate_const<_Tp>& __pc1, propagate_const<_Tp>& __pc2) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value)
467 swap(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
471 _LIBCPP_CONSTEXPR const _Tp& get_underlying(const propagate_const<_Tp>& __pt) _NOEXCEPT
477 _LIBCPP_CONSTEXPR _Tp& get_underlying(propagate_const<_Tp>& __pt) _NOEXCEPT
482 _LIBCPP_END_NAMESPACE_LFTS_V2
484 _LIBCPP_BEGIN_NAMESPACE_STD
487 struct hash<experimental::fundamentals_v2::propagate_const<_Tp>>
489 typedef size_t result_type;
490 typedef experimental::fundamentals_v2::propagate_const<_Tp> argument_type;
492 size_t operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1) const
494 return std::hash<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1));
499 struct equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
501 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
502 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
504 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
505 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
507 return std::equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
512 struct not_equal_to<experimental::fundamentals_v2::propagate_const<_Tp>>
514 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
515 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
517 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
518 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
520 return std::not_equal_to<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
525 struct less<experimental::fundamentals_v2::propagate_const<_Tp>>
527 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
528 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
530 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
531 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
533 return std::less<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
538 struct greater<experimental::fundamentals_v2::propagate_const<_Tp>>
540 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
541 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
543 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
544 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
546 return std::greater<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
551 struct less_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
553 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
554 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
556 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
557 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
559 return std::less_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
564 struct greater_equal<experimental::fundamentals_v2::propagate_const<_Tp>>
566 typedef experimental::fundamentals_v2::propagate_const<_Tp> first_argument_type;
567 typedef experimental::fundamentals_v2::propagate_const<_Tp> second_argument_type;
569 bool operator()(const experimental::fundamentals_v2::propagate_const<_Tp>& __pc1,
570 const experimental::fundamentals_v2::propagate_const<_Tp>& __pc2) const
572 return std::greater_equal<_Tp>()(_VSTD_LFTS_V2::get_underlying(__pc1), _VSTD_LFTS_V2::get_underlying(__pc2));
576 _LIBCPP_END_NAMESPACE_STD
578 #endif // _LIBCPP_STD_VER > 11
579 #endif // _LIBCPP_EXPERIMENTAL_PROPAGATE_CONST