1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
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 |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H |
11 | #define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H |
12 | |
13 | #include <__compare/synth_three_way.h> |
14 | #include <__concepts/boolean_testable.h> |
15 | #include <__config> |
16 | #include <__functional/invoke.h> |
17 | #include <__functional/weak_result_type.h> |
18 | #include <__memory/addressof.h> |
19 | #include <__type_traits/enable_if.h> |
20 | #include <__type_traits/is_const.h> |
21 | #include <__type_traits/remove_cvref.h> |
22 | #include <__type_traits/void_t.h> |
23 | #include <__utility/declval.h> |
24 | #include <__utility/forward.h> |
25 | |
26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
27 | # pragma GCC system_header |
28 | #endif |
29 | |
30 | _LIBCPP_BEGIN_NAMESPACE_STD |
31 | |
32 | template <class _Tp> |
33 | class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> { |
34 | public: |
35 | // types |
36 | typedef _Tp type; |
37 | |
38 | private: |
39 | type* __f_; |
40 | |
41 | static void __fun(_Tp&) _NOEXCEPT; |
42 | static void __fun(_Tp&&) = delete; // NOLINT(modernize-use-equals-delete) ; This is llvm.org/PR54276 |
43 | |
44 | public: |
45 | template <class _Up, |
46 | class = __void_t<decltype(__fun(std::declval<_Up>()))>, |
47 | __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, int> = 0> |
48 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper(_Up&& __u) |
49 | _NOEXCEPT_(noexcept(__fun(std::declval<_Up>()))) { |
50 | type& __f = static_cast<_Up&&>(__u); |
51 | __f_ = std::addressof(__f); |
52 | } |
53 | |
54 | // access |
55 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator type&() const _NOEXCEPT { return *__f_; } |
56 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 type& get() const _NOEXCEPT { return *__f_; } |
57 | |
58 | // invoke |
59 | template <class... _ArgTypes> |
60 | _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<type&, _ArgTypes...>::type |
61 | operator()(_ArgTypes&&... __args) const |
62 | #if _LIBCPP_STD_VER >= 17 |
63 | // Since is_nothrow_invocable requires C++17 LWG3764 is not backported |
64 | // to earlier versions. |
65 | noexcept(is_nothrow_invocable_v<_Tp&, _ArgTypes...>) |
66 | #endif |
67 | { |
68 | return std::__invoke(get(), std::forward<_ArgTypes>(__args)...); |
69 | } |
70 | |
71 | #if _LIBCPP_STD_VER >= 26 |
72 | |
73 | // [refwrap.comparisons], comparisons |
74 | |
75 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper __y) |
76 | requires requires { |
77 | { __x.get() == __y.get() } -> __boolean_testable; |
78 | } |
79 | { |
80 | return __x.get() == __y.get(); |
81 | } |
82 | |
83 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, const _Tp& __y) |
84 | requires requires { |
85 | { __x.get() == __y } -> __boolean_testable; |
86 | } |
87 | { |
88 | return __x.get() == __y; |
89 | } |
90 | |
91 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(reference_wrapper __x, reference_wrapper<const _Tp> __y) |
92 | requires(!is_const_v<_Tp>) && requires { |
93 | { __x.get() == __y.get() } -> __boolean_testable; |
94 | } |
95 | { |
96 | return __x.get() == __y.get(); |
97 | } |
98 | |
99 | _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, reference_wrapper __y) |
100 | requires requires { std::__synth_three_way(__x.get(), __y.get()); } |
101 | { |
102 | return std::__synth_three_way(__x.get(), __y.get()); |
103 | } |
104 | |
105 | _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, const _Tp& __y) |
106 | requires requires { std::__synth_three_way(__x.get(), __y); } |
107 | { |
108 | return std::__synth_three_way(__x.get(), __y); |
109 | } |
110 | |
111 | _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(reference_wrapper __x, reference_wrapper<const _Tp> __y) |
112 | requires(!is_const_v<_Tp>) && requires { std::__synth_three_way(__x.get(), __y.get()); } |
113 | { |
114 | return std::__synth_three_way(__x.get(), __y.get()); |
115 | } |
116 | |
117 | #endif // _LIBCPP_STD_VER >= 26 |
118 | }; |
119 | |
120 | #if _LIBCPP_STD_VER >= 17 |
121 | template <class _Tp> |
122 | reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; |
123 | #endif |
124 | |
125 | template <class _Tp> |
126 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT { |
127 | return reference_wrapper<_Tp>(__t); |
128 | } |
129 | |
130 | template <class _Tp> |
131 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> |
132 | ref(reference_wrapper<_Tp> __t) _NOEXCEPT { |
133 | return __t; |
134 | } |
135 | |
136 | template <class _Tp> |
137 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp> cref(const _Tp& __t) _NOEXCEPT { |
138 | return reference_wrapper<const _Tp>(__t); |
139 | } |
140 | |
141 | template <class _Tp> |
142 | inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp> |
143 | cref(reference_wrapper<_Tp> __t) _NOEXCEPT { |
144 | return __t; |
145 | } |
146 | |
147 | template <class _Tp> |
148 | void ref(const _Tp&&) = delete; |
149 | template <class _Tp> |
150 | void cref(const _Tp&&) = delete; |
151 | |
152 | _LIBCPP_END_NAMESPACE_STD |
153 | |
154 | #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H |
155 | |