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 <__config>
14 #include <__functional/weak_result_type.h>
15 #include <__memory/addressof.h>
16 #include <__utility/forward.h>
17 #include <type_traits>
18 
19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20 #  pragma GCC system_header
21 #  pragma clang include_instead(<functional>)
22 #endif
23 
24 _LIBCPP_BEGIN_NAMESPACE_STD
25 
26 template <class _Tp>
27 class _LIBCPP_TEMPLATE_VIS reference_wrapper
28 #if _LIBCPP_STD_VER <= 17 || !defined(_LIBCPP_ABI_NO_BINDER_BASES)
29     : public __weak_result_type<_Tp>
30 #endif
31 {
32 public:
33     // types
34     typedef _Tp type;
35 private:
36     type* __f_;
37 
38     static void __fun(_Tp&) _NOEXCEPT;
39     static void __fun(_Tp&&) = delete;
40 
41 public:
42     template <class _Up, class = __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(declval<_Up>())) > >
43     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
44     reference_wrapper(_Up&& __u) _NOEXCEPT_(noexcept(__fun(declval<_Up>()))) {
45         type& __f = static_cast<_Up&&>(__u);
46         __f_ = _VSTD::addressof(__f);
47     }
48 
49     // access
50     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
51     operator type&() const _NOEXCEPT {return *__f_;}
52     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
53     type& get() const _NOEXCEPT {return *__f_;}
54 
55 #ifndef _LIBCPP_CXX03_LANG
56     // invoke
57     template <class... _ArgTypes>
58     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
59     typename __invoke_of<type&, _ArgTypes...>::type
60     operator() (_ArgTypes&&... __args) const {
61         return _VSTD::__invoke(get(), _VSTD::forward<_ArgTypes>(__args)...);
62     }
63 #else
64 
65     _LIBCPP_INLINE_VISIBILITY
66     typename __invoke_return<type>::type
67     operator() () const {
68         return _VSTD::__invoke(get());
69     }
70 
71     template <class _A0>
72     _LIBCPP_INLINE_VISIBILITY
73     typename __invoke_return0<type, _A0>::type
74     operator() (_A0& __a0) const {
75         return _VSTD::__invoke(get(), __a0);
76     }
77 
78     template <class _A0>
79     _LIBCPP_INLINE_VISIBILITY
80     typename __invoke_return0<type, _A0 const>::type
81     operator() (_A0 const& __a0) const {
82         return _VSTD::__invoke(get(), __a0);
83     }
84 
85     template <class _A0, class _A1>
86     _LIBCPP_INLINE_VISIBILITY
87     typename __invoke_return1<type, _A0, _A1>::type
88     operator() (_A0& __a0, _A1& __a1) const {
89         return _VSTD::__invoke(get(), __a0, __a1);
90     }
91 
92     template <class _A0, class _A1>
93     _LIBCPP_INLINE_VISIBILITY
94     typename __invoke_return1<type, _A0 const, _A1>::type
95     operator() (_A0 const& __a0, _A1& __a1) const {
96         return _VSTD::__invoke(get(), __a0, __a1);
97     }
98 
99     template <class _A0, class _A1>
100     _LIBCPP_INLINE_VISIBILITY
101     typename __invoke_return1<type, _A0, _A1 const>::type
102     operator() (_A0& __a0, _A1 const& __a1) const {
103         return _VSTD::__invoke(get(), __a0, __a1);
104     }
105 
106     template <class _A0, class _A1>
107     _LIBCPP_INLINE_VISIBILITY
108     typename __invoke_return1<type, _A0 const, _A1 const>::type
109     operator() (_A0 const& __a0, _A1 const& __a1) const {
110         return _VSTD::__invoke(get(), __a0, __a1);
111     }
112 
113     template <class _A0, class _A1, class _A2>
114     _LIBCPP_INLINE_VISIBILITY
115     typename __invoke_return2<type, _A0, _A1, _A2>::type
116     operator() (_A0& __a0, _A1& __a1, _A2& __a2) const {
117         return _VSTD::__invoke(get(), __a0, __a1, __a2);
118     }
119 
120     template <class _A0, class _A1, class _A2>
121     _LIBCPP_INLINE_VISIBILITY
122     typename __invoke_return2<type, _A0 const, _A1, _A2>::type
123     operator() (_A0 const& __a0, _A1& __a1, _A2& __a2) const {
124         return _VSTD::__invoke(get(), __a0, __a1, __a2);
125     }
126 
127     template <class _A0, class _A1, class _A2>
128     _LIBCPP_INLINE_VISIBILITY
129     typename __invoke_return2<type, _A0, _A1 const, _A2>::type
130     operator() (_A0& __a0, _A1 const& __a1, _A2& __a2) const {
131         return _VSTD::__invoke(get(), __a0, __a1, __a2);
132     }
133 
134     template <class _A0, class _A1, class _A2>
135     _LIBCPP_INLINE_VISIBILITY
136     typename __invoke_return2<type, _A0, _A1, _A2 const>::type
137     operator() (_A0& __a0, _A1& __a1, _A2 const& __a2) const {
138         return _VSTD::__invoke(get(), __a0, __a1, __a2);
139     }
140 
141     template <class _A0, class _A1, class _A2>
142     _LIBCPP_INLINE_VISIBILITY
143     typename __invoke_return2<type, _A0 const, _A1 const, _A2>::type
144     operator() (_A0 const& __a0, _A1 const& __a1, _A2& __a2) const {
145         return _VSTD::__invoke(get(), __a0, __a1, __a2);
146     }
147 
148     template <class _A0, class _A1, class _A2>
149     _LIBCPP_INLINE_VISIBILITY
150     typename __invoke_return2<type, _A0 const, _A1, _A2 const>::type
151     operator() (_A0 const& __a0, _A1& __a1, _A2 const& __a2) const {
152         return _VSTD::__invoke(get(), __a0, __a1, __a2);
153     }
154 
155     template <class _A0, class _A1, class _A2>
156     _LIBCPP_INLINE_VISIBILITY
157     typename __invoke_return2<type, _A0, _A1 const, _A2 const>::type
158     operator() (_A0& __a0, _A1 const& __a1, _A2 const& __a2) const {
159         return _VSTD::__invoke(get(), __a0, __a1, __a2);
160     }
161 
162     template <class _A0, class _A1, class _A2>
163     _LIBCPP_INLINE_VISIBILITY
164     typename __invoke_return2<type, _A0 const, _A1 const, _A2 const>::type
165     operator() (_A0 const& __a0, _A1 const& __a1, _A2 const& __a2) const {
166         return _VSTD::__invoke(get(), __a0, __a1, __a2);
167     }
168 #endif // _LIBCPP_CXX03_LANG
169 };
170 
171 #if _LIBCPP_STD_VER > 14
172 template <class _Tp>
173 reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
174 #endif
175 
176 template <class _Tp>
177 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
178 reference_wrapper<_Tp>
179 ref(_Tp& __t) _NOEXCEPT
180 {
181     return reference_wrapper<_Tp>(__t);
182 }
183 
184 template <class _Tp>
185 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
186 reference_wrapper<_Tp>
187 ref(reference_wrapper<_Tp> __t) _NOEXCEPT
188 {
189     return __t;
190 }
191 
192 template <class _Tp>
193 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
194 reference_wrapper<const _Tp>
195 cref(const _Tp& __t) _NOEXCEPT
196 {
197     return reference_wrapper<const _Tp>(__t);
198 }
199 
200 template <class _Tp>
201 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
202 reference_wrapper<const _Tp>
203 cref(reference_wrapper<_Tp> __t) _NOEXCEPT
204 {
205     return __t;
206 }
207 
208 template <class _Tp> void ref(const _Tp&&) = delete;
209 template <class _Tp> void cref(const _Tp&&) = delete;
210 
211 _LIBCPP_END_NAMESPACE_STD
212 
213 #endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
214