blob: 6a385c74c989a37257e9b84fd396e5f2b6544b5d [file] [log] [blame]
Eric Fiselier5be45122015-07-14 20:16:15 +00001//===----------------------------------------------------------------------===//
2//
Chandler Carruth57b08b02019-01-19 10:56:40 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier5be45122015-07-14 20:16:15 +00006//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++98, c++03, c++11, c++14
10
11// <functional>
12
Louis Dionne6c49e1c2019-04-03 17:54:37 +000013// template<class F, class... Args>
14// invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) // C++17
15// noexcept(is_nothrow_invocable_v<_Fn, _Args...>);
Eric Fiselier5be45122015-07-14 20:16:15 +000016
17/// C++14 [func.def] 20.9.0
18/// (1) The following definitions apply to this Clause:
19/// (2) A call signature is the name of a return type followed by a parenthesized
20/// comma-separated list of zero or more argument types.
21/// (3) A callable type is a function object type (20.9) or a pointer to member.
22/// (4) A callable object is an object of a callable type.
23/// (5) A call wrapper type is a type that holds a callable object and supports
24/// a call operation that forwards to that object.
25/// (6) A call wrapper is an object of a call wrapper type.
26/// (7) A target object is the callable object held by a call wrapper.
27
28/// C++14 [func.require] 20.9.1
29///
30/// Define INVOKE (f, t1, t2, ..., tN) as follows:
Eric Fiselier16270a02015-07-14 20:45:48 +000031/// (1.1) - (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of
Eric Fiselier5be45122015-07-14 20:16:15 +000032/// type T or a reference to an object of type T or a reference to an object of a type derived from T;
Eric Fiselier16270a02015-07-14 20:45:48 +000033/// (1.2) - ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of
Eric Fiselier5be45122015-07-14 20:16:15 +000034/// the types described in the previous item;
Eric Fiselier16270a02015-07-14 20:45:48 +000035/// (1.3) - t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a
Eric Fiselier5be45122015-07-14 20:16:15 +000036/// reference to an object of type T or a reference to an object of a type derived from T;
Eric Fiselier16270a02015-07-14 20:45:48 +000037/// (1.4) - (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types
Eric Fiselier5be45122015-07-14 20:16:15 +000038/// described in the previous item;
Eric Fiselier16270a02015-07-14 20:45:48 +000039/// (1.5) - f(t1, t2, ..., tN) in all other cases.
Eric Fiselier5be45122015-07-14 20:16:15 +000040
41#include <functional>
42#include <type_traits>
Marshall Clowd1180f42015-11-10 16:10:17 +000043#include <utility> // for std::move
Eric Fiselier5be45122015-07-14 20:16:15 +000044#include <cassert>
45
Marshall Clow7fc6a552019-05-31 18:35:30 +000046#include "test_macros.h"
47
Eric Fiselier5be45122015-07-14 20:16:15 +000048struct NonCopyable {
49 NonCopyable() {}
50private:
51 NonCopyable(NonCopyable const&) = delete;
52 NonCopyable& operator=(NonCopyable const&) = delete;
53};
54
55struct TestClass {
56 explicit TestClass(int x) : data(x) {}
57
58 int& operator()(NonCopyable&&) & { return data; }
59 int const& operator()(NonCopyable&&) const & { return data; }
60 int volatile& operator()(NonCopyable&&) volatile & { return data; }
61 int const volatile& operator()(NonCopyable&&) const volatile & { return data; }
62
63 int&& operator()(NonCopyable&&) && { return std::move(data); }
64 int const&& operator()(NonCopyable&&) const && { return std::move(data); }
65 int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
66 int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }
67
68 int data;
69private:
70 TestClass(TestClass const&) = delete;
71 TestClass& operator=(TestClass const&) = delete;
72};
73
74struct DerivedFromTestClass : public TestClass {
75 explicit DerivedFromTestClass(int x) : TestClass(x) {}
76};
77
78int& foo(NonCopyable&&) {
79 static int data = 42;
80 return data;
81}
82
83template <class Signature, class Expect, class Functor>
84void test_b12(Functor&& f) {
85 // Create the callable object.
86 typedef Signature TestClass::*ClassFunc;
87 ClassFunc func_ptr = &TestClass::operator();
88
89 // Create the dummy arg.
90 NonCopyable arg;
91
92 // Check that the deduced return type of invoke is what is expected.
93 typedef decltype(
94 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
95 ) DeducedReturnType;
96 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
97
98 // Check that result_of_t matches Expect.
99 typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
100 ResultOfReturnType;
101 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
102
103 // Run invoke and check the return value.
104 DeducedReturnType ret =
105 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
106 assert(ret == 42);
107}
108
109template <class Expect, class Functor>
110void test_b34(Functor&& f) {
111 // Create the callable object.
112 typedef int TestClass::*ClassFunc;
113 ClassFunc func_ptr = &TestClass::data;
114
115 // Check that the deduced return type of invoke is what is expected.
116 typedef decltype(
117 std::invoke(func_ptr, std::forward<Functor>(f))
118 ) DeducedReturnType;
119 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
120
121 // Check that result_of_t matches Expect.
122 typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
123 ResultOfReturnType;
124 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
125
126 // Run invoke and check the return value.
127 DeducedReturnType ret =
128 std::invoke(func_ptr, std::forward<Functor>(f));
129 assert(ret == 42);
130}
131
132template <class Expect, class Functor>
133void test_b5(Functor&& f) {
134 NonCopyable arg;
135
136 // Check that the deduced return type of invoke is what is expected.
137 typedef decltype(
138 std::invoke(std::forward<Functor>(f), std::move(arg))
139 ) DeducedReturnType;
140 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
141
142 // Check that result_of_t matches Expect.
143 typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
144 ResultOfReturnType;
145 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
146
147 // Run invoke and check the return value.
148 DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
149 assert(ret == 42);
150}
151
152void bullet_one_two_tests() {
153 {
154 TestClass cl(42);
155 test_b12<int&(NonCopyable&&) &, int&>(cl);
156 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
157 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
158 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
159
160 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
161 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
162 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
163 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
164 }
165 {
166 DerivedFromTestClass cl(42);
167 test_b12<int&(NonCopyable&&) &, int&>(cl);
168 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
169 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
170 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
171
172 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
173 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
174 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
175 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
176 }
177 {
178 TestClass cl_obj(42);
Eric Fiselier2152fd72016-04-18 06:17:30 +0000179 std::reference_wrapper<TestClass> cl(cl_obj);
180 test_b12<int&(NonCopyable&&) &, int&>(cl);
181 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
182 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
183 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
184
185 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
186 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
187 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));
188 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));
189 }
190 {
191 DerivedFromTestClass cl_obj(42);
192 std::reference_wrapper<DerivedFromTestClass> cl(cl_obj);
193 test_b12<int&(NonCopyable&&) &, int&>(cl);
194 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
195 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
196 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
197
198 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
199 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
200 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));
201 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));
202 }
203 {
204 TestClass cl_obj(42);
Eric Fiselier5be45122015-07-14 20:16:15 +0000205 TestClass *cl = &cl_obj;
206 test_b12<int&(NonCopyable&&) &, int&>(cl);
207 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
208 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
209 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
210 }
211 {
212 DerivedFromTestClass cl_obj(42);
213 DerivedFromTestClass *cl = &cl_obj;
214 test_b12<int&(NonCopyable&&) &, int&>(cl);
215 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
216 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
217 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
218 }
219}
220
221void bullet_three_four_tests() {
222 {
223 typedef TestClass Fn;
224 Fn cl(42);
225 test_b34<int&>(cl);
226 test_b34<int const&>(static_cast<Fn const&>(cl));
227 test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
228 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
229
230 test_b34<int&&>(static_cast<Fn &&>(cl));
231 test_b34<int const&&>(static_cast<Fn const&&>(cl));
232 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
233 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
234 }
235 {
236 typedef DerivedFromTestClass Fn;
237 Fn cl(42);
238 test_b34<int&>(cl);
239 test_b34<int const&>(static_cast<Fn const&>(cl));
240 test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
241 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
242
243 test_b34<int&&>(static_cast<Fn &&>(cl));
244 test_b34<int const&&>(static_cast<Fn const&&>(cl));
245 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
246 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
247 }
248 {
249 typedef TestClass Fn;
Eric Fiselier2152fd72016-04-18 06:17:30 +0000250 Fn cl(42);
251 test_b34<int&>(std::reference_wrapper<Fn>(cl));
252 test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
253 test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));
254 test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));
255 }
256 {
257 typedef DerivedFromTestClass Fn;
258 Fn cl(42);
259 test_b34<int&>(std::reference_wrapper<Fn>(cl));
260 test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
261 test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));
262 test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));
263 }
264 {
265 typedef TestClass Fn;
Eric Fiselier5be45122015-07-14 20:16:15 +0000266 Fn cl_obj(42);
267 Fn* cl = &cl_obj;
268 test_b34<int&>(cl);
269 test_b34<int const&>(static_cast<Fn const*>(cl));
270 test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
271 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
272 }
273 {
274 typedef DerivedFromTestClass Fn;
275 Fn cl_obj(42);
276 Fn* cl = &cl_obj;
277 test_b34<int&>(cl);
278 test_b34<int const&>(static_cast<Fn const*>(cl));
279 test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
280 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
281 }
282}
283
284void bullet_five_tests() {
285 using FooType = int&(NonCopyable&&);
286 {
287 FooType& fn = foo;
288 test_b5<int &>(fn);
289 }
290 {
291 FooType* fn = foo;
292 test_b5<int &>(fn);
293 }
294 {
295 typedef TestClass Fn;
296 Fn cl(42);
297 test_b5<int&>(cl);
298 test_b5<int const&>(static_cast<Fn const&>(cl));
299 test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
300 test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
301
302 test_b5<int&&>(static_cast<Fn &&>(cl));
303 test_b5<int const&&>(static_cast<Fn const&&>(cl));
304 test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
305 test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
306 }
307}
308
Eric Fiselier57257562016-06-02 01:25:41 +0000309struct CopyThrows {
310 CopyThrows() {}
311 CopyThrows(CopyThrows const&) {}
312 CopyThrows(CopyThrows&&) noexcept {}
313};
314
315struct NoThrowCallable {
316 void operator()() noexcept {}
317 void operator()(CopyThrows) noexcept {}
318};
319
320struct ThrowsCallable {
321 void operator()() {}
322};
323
324struct MemberObj {
325 int x;
326};
327
328void noexcept_test() {
329 {
Eric Fiselierc1d08ff2016-06-22 00:58:06 +0000330 NoThrowCallable obj; ((void)obj); // suppress unused warning
331 CopyThrows arg; ((void)arg); // suppress unused warning
Eric Fiselier7a580d02016-06-22 01:10:14 +0000332 static_assert(noexcept(std::invoke(obj)), "");
333 static_assert(!noexcept(std::invoke(obj, arg)), "");
334 static_assert(noexcept(std::invoke(obj, std::move(arg))), "");
Eric Fiselier57257562016-06-02 01:25:41 +0000335 }
336 {
Eric Fiselierc1d08ff2016-06-22 00:58:06 +0000337 ThrowsCallable obj; ((void)obj); // suppress unused warning
Eric Fiselier7a580d02016-06-22 01:10:14 +0000338 static_assert(!noexcept(std::invoke(obj)), "");
Eric Fiselier57257562016-06-02 01:25:41 +0000339 }
340 {
Eric Fiselierc1d08ff2016-06-22 00:58:06 +0000341 MemberObj obj{42}; ((void)obj); // suppress unused warning.
Eric Fiselier7a580d02016-06-22 01:10:14 +0000342 static_assert(noexcept(std::invoke(&MemberObj::x, obj)), "");
Eric Fiselier57257562016-06-02 01:25:41 +0000343 }
344}
345
JF Bastien2df59c52019-02-04 20:31:13 +0000346int main(int, char**) {
Eric Fiselier5be45122015-07-14 20:16:15 +0000347 bullet_one_two_tests();
348 bullet_three_four_tests();
349 bullet_five_tests();
Eric Fiselier57257562016-06-02 01:25:41 +0000350 noexcept_test();
JF Bastien2df59c52019-02-04 20:31:13 +0000351
352 return 0;
Eric Fiselier5be45122015-07-14 20:16:15 +0000353}