blob: d1ae6b7809ce84a3f0b792f37c76555e575a6b34 [file] [log] [blame]
Eric Fiselier5be45122015-07-14 20:16:15 +00001//===----------------------------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// UNSUPPORTED: c++98, c++03, c++11, c++14
11
12// <functional>
13
14// template <class F, class ...Args>
15// result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...);
16
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
46struct NonCopyable {
47 NonCopyable() {}
48private:
49 NonCopyable(NonCopyable const&) = delete;
50 NonCopyable& operator=(NonCopyable const&) = delete;
51};
52
53struct TestClass {
54 explicit TestClass(int x) : data(x) {}
55
56 int& operator()(NonCopyable&&) & { return data; }
57 int const& operator()(NonCopyable&&) const & { return data; }
58 int volatile& operator()(NonCopyable&&) volatile & { return data; }
59 int const volatile& operator()(NonCopyable&&) const volatile & { return data; }
60
61 int&& operator()(NonCopyable&&) && { return std::move(data); }
62 int const&& operator()(NonCopyable&&) const && { return std::move(data); }
63 int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
64 int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }
65
66 int data;
67private:
68 TestClass(TestClass const&) = delete;
69 TestClass& operator=(TestClass const&) = delete;
70};
71
72struct DerivedFromTestClass : public TestClass {
73 explicit DerivedFromTestClass(int x) : TestClass(x) {}
74};
75
76int& foo(NonCopyable&&) {
77 static int data = 42;
78 return data;
79}
80
81template <class Signature, class Expect, class Functor>
82void test_b12(Functor&& f) {
83 // Create the callable object.
84 typedef Signature TestClass::*ClassFunc;
85 ClassFunc func_ptr = &TestClass::operator();
86
87 // Create the dummy arg.
88 NonCopyable arg;
89
90 // Check that the deduced return type of invoke is what is expected.
91 typedef decltype(
92 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
93 ) DeducedReturnType;
94 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
95
96 // Check that result_of_t matches Expect.
97 typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
98 ResultOfReturnType;
99 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
100
101 // Run invoke and check the return value.
102 DeducedReturnType ret =
103 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
104 assert(ret == 42);
105}
106
107template <class Expect, class Functor>
108void test_b34(Functor&& f) {
109 // Create the callable object.
110 typedef int TestClass::*ClassFunc;
111 ClassFunc func_ptr = &TestClass::data;
112
113 // Check that the deduced return type of invoke is what is expected.
114 typedef decltype(
115 std::invoke(func_ptr, std::forward<Functor>(f))
116 ) DeducedReturnType;
117 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
118
119 // Check that result_of_t matches Expect.
120 typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
121 ResultOfReturnType;
122 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
123
124 // Run invoke and check the return value.
125 DeducedReturnType ret =
126 std::invoke(func_ptr, std::forward<Functor>(f));
127 assert(ret == 42);
128}
129
130template <class Expect, class Functor>
131void test_b5(Functor&& f) {
132 NonCopyable arg;
133
134 // Check that the deduced return type of invoke is what is expected.
135 typedef decltype(
136 std::invoke(std::forward<Functor>(f), std::move(arg))
137 ) DeducedReturnType;
138 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
139
140 // Check that result_of_t matches Expect.
141 typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
142 ResultOfReturnType;
143 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
144
145 // Run invoke and check the return value.
146 DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
147 assert(ret == 42);
148}
149
150void bullet_one_two_tests() {
151 {
152 TestClass cl(42);
153 test_b12<int&(NonCopyable&&) &, int&>(cl);
154 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
155 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
156 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
157
158 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
159 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
160 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
161 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
162 }
163 {
164 DerivedFromTestClass cl(42);
165 test_b12<int&(NonCopyable&&) &, int&>(cl);
166 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
167 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
168 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
169
170 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
171 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
172 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
173 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
174 }
175 {
176 TestClass cl_obj(42);
Eric Fiselier2152fd72016-04-18 06:17:30 +0000177 std::reference_wrapper<TestClass> cl(cl_obj);
178 test_b12<int&(NonCopyable&&) &, int&>(cl);
179 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
180 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
181 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
182
183 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
184 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
185 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));
186 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));
187 }
188 {
189 DerivedFromTestClass cl_obj(42);
190 std::reference_wrapper<DerivedFromTestClass> cl(cl_obj);
191 test_b12<int&(NonCopyable&&) &, int&>(cl);
192 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
193 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
194 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
195
196 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl));
197 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl));
198 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl));
199 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl));
200 }
201 {
202 TestClass cl_obj(42);
Eric Fiselier5be45122015-07-14 20:16:15 +0000203 TestClass *cl = &cl_obj;
204 test_b12<int&(NonCopyable&&) &, int&>(cl);
205 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
206 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
207 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
208 }
209 {
210 DerivedFromTestClass cl_obj(42);
211 DerivedFromTestClass *cl = &cl_obj;
212 test_b12<int&(NonCopyable&&) &, int&>(cl);
213 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
214 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
215 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
216 }
217}
218
219void bullet_three_four_tests() {
220 {
221 typedef TestClass Fn;
222 Fn cl(42);
223 test_b34<int&>(cl);
224 test_b34<int const&>(static_cast<Fn const&>(cl));
225 test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
226 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
227
228 test_b34<int&&>(static_cast<Fn &&>(cl));
229 test_b34<int const&&>(static_cast<Fn const&&>(cl));
230 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
231 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
232 }
233 {
234 typedef DerivedFromTestClass Fn;
235 Fn cl(42);
236 test_b34<int&>(cl);
237 test_b34<int const&>(static_cast<Fn const&>(cl));
238 test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
239 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
240
241 test_b34<int&&>(static_cast<Fn &&>(cl));
242 test_b34<int const&&>(static_cast<Fn const&&>(cl));
243 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
244 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
245 }
246 {
247 typedef TestClass Fn;
Eric Fiselier2152fd72016-04-18 06:17:30 +0000248 Fn cl(42);
249 test_b34<int&>(std::reference_wrapper<Fn>(cl));
250 test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
251 test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));
252 test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));
253 }
254 {
255 typedef DerivedFromTestClass Fn;
256 Fn cl(42);
257 test_b34<int&>(std::reference_wrapper<Fn>(cl));
258 test_b34<int const&>(std::reference_wrapper<Fn const>(cl));
259 test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl));
260 test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl));
261 }
262 {
263 typedef TestClass Fn;
Eric Fiselier5be45122015-07-14 20:16:15 +0000264 Fn cl_obj(42);
265 Fn* cl = &cl_obj;
266 test_b34<int&>(cl);
267 test_b34<int const&>(static_cast<Fn const*>(cl));
268 test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
269 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
270 }
271 {
272 typedef DerivedFromTestClass Fn;
273 Fn cl_obj(42);
274 Fn* cl = &cl_obj;
275 test_b34<int&>(cl);
276 test_b34<int const&>(static_cast<Fn const*>(cl));
277 test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
278 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
279 }
280}
281
282void bullet_five_tests() {
283 using FooType = int&(NonCopyable&&);
284 {
285 FooType& fn = foo;
286 test_b5<int &>(fn);
287 }
288 {
289 FooType* fn = foo;
290 test_b5<int &>(fn);
291 }
292 {
293 typedef TestClass Fn;
294 Fn cl(42);
295 test_b5<int&>(cl);
296 test_b5<int const&>(static_cast<Fn const&>(cl));
297 test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
298 test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
299
300 test_b5<int&&>(static_cast<Fn &&>(cl));
301 test_b5<int const&&>(static_cast<Fn const&&>(cl));
302 test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
303 test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
304 }
305}
306
Eric Fiselier57257562016-06-02 01:25:41 +0000307struct CopyThrows {
308 CopyThrows() {}
309 CopyThrows(CopyThrows const&) {}
310 CopyThrows(CopyThrows&&) noexcept {}
311};
312
313struct NoThrowCallable {
314 void operator()() noexcept {}
315 void operator()(CopyThrows) noexcept {}
316};
317
318struct ThrowsCallable {
319 void operator()() {}
320};
321
322struct MemberObj {
323 int x;
324};
325
326void noexcept_test() {
327 {
Eric Fiselierc1d08ff2016-06-22 00:58:06 +0000328 NoThrowCallable obj; ((void)obj); // suppress unused warning
329 CopyThrows arg; ((void)arg); // suppress unused warning
Eric Fiselier7a580d02016-06-22 01:10:14 +0000330 static_assert(noexcept(std::invoke(obj)), "");
331 static_assert(!noexcept(std::invoke(obj, arg)), "");
332 static_assert(noexcept(std::invoke(obj, std::move(arg))), "");
Eric Fiselier57257562016-06-02 01:25:41 +0000333 }
334 {
Eric Fiselierc1d08ff2016-06-22 00:58:06 +0000335 ThrowsCallable obj; ((void)obj); // suppress unused warning
Eric Fiselier7a580d02016-06-22 01:10:14 +0000336 static_assert(!noexcept(std::invoke(obj)), "");
Eric Fiselier57257562016-06-02 01:25:41 +0000337 }
338 {
Eric Fiselierc1d08ff2016-06-22 00:58:06 +0000339 MemberObj obj{42}; ((void)obj); // suppress unused warning.
Eric Fiselier7a580d02016-06-22 01:10:14 +0000340 static_assert(noexcept(std::invoke(&MemberObj::x, obj)), "");
Eric Fiselier57257562016-06-02 01:25:41 +0000341 }
342}
343
Eric Fiselier5be45122015-07-14 20:16:15 +0000344int main() {
345 bullet_one_two_tests();
346 bullet_three_four_tests();
347 bullet_five_tests();
Eric Fiselier57257562016-06-02 01:25:41 +0000348 noexcept_test();
Eric Fiselier5be45122015-07-14 20:16:15 +0000349}