xref: /llvm-project/libcxx/test/std/utilities/function.objects/func.invoke/invoke.pass.cpp (revision d1180f4abc267ed041744df2204b846f18f6d554)
1 //===----------------------------------------------------------------------===//
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:
31 ///   (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
32 ///   type T or a reference to an object of type T or a reference to an object of a type derived from T;
33 ///   (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
34 ///   the types described in the previous item;
35 ///   (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
36 ///   reference to an object of type T or a reference to an object of a type derived from T;
37 ///   (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
38 ///   described in the previous item;
39 ///   (1.5) - f(t1, t2, ..., tN) in all other cases.
40 
41 #include <functional>
42 #include <type_traits>
43 #include <utility> // for std::move
44 #include <cassert>
45 
46 struct NonCopyable {
47     NonCopyable() {}
48 private:
49     NonCopyable(NonCopyable const&) = delete;
50     NonCopyable& operator=(NonCopyable const&) = delete;
51 };
52 
53 struct 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;
67 private:
68     TestClass(TestClass const&) = delete;
69     TestClass& operator=(TestClass const&) = delete;
70 };
71 
72 struct DerivedFromTestClass : public TestClass {
73     explicit DerivedFromTestClass(int x) : TestClass(x) {}
74 };
75 
76 int& foo(NonCopyable&&) {
77     static int data = 42;
78     return data;
79 }
80 
81 template <class Signature,  class Expect, class Functor>
82 void 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 
107 template <class Expect, class Functor>
108 void 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 
130 template <class Expect, class Functor>
131 void 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 
150 void 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);
177         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     {
184         DerivedFromTestClass cl_obj(42);
185         DerivedFromTestClass *cl = &cl_obj;
186         test_b12<int&(NonCopyable&&) &, int&>(cl);
187         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
188         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
189         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
190     }
191 }
192 
193 void bullet_three_four_tests() {
194     {
195         typedef TestClass Fn;
196         Fn cl(42);
197         test_b34<int&>(cl);
198         test_b34<int const&>(static_cast<Fn const&>(cl));
199         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
200         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
201 
202         test_b34<int&&>(static_cast<Fn &&>(cl));
203         test_b34<int const&&>(static_cast<Fn const&&>(cl));
204         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
205         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
206     }
207     {
208         typedef DerivedFromTestClass Fn;
209         Fn cl(42);
210         test_b34<int&>(cl);
211         test_b34<int const&>(static_cast<Fn const&>(cl));
212         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
213         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
214 
215         test_b34<int&&>(static_cast<Fn &&>(cl));
216         test_b34<int const&&>(static_cast<Fn const&&>(cl));
217         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
218         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
219     }
220     {
221         typedef TestClass Fn;
222         Fn cl_obj(42);
223         Fn* cl = &cl_obj;
224         test_b34<int&>(cl);
225         test_b34<int const&>(static_cast<Fn const*>(cl));
226         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
227         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
228     }
229     {
230         typedef DerivedFromTestClass Fn;
231         Fn cl_obj(42);
232         Fn* cl = &cl_obj;
233         test_b34<int&>(cl);
234         test_b34<int const&>(static_cast<Fn const*>(cl));
235         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
236         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
237     }
238 }
239 
240 void bullet_five_tests() {
241     using FooType = int&(NonCopyable&&);
242     {
243         FooType& fn = foo;
244         test_b5<int &>(fn);
245     }
246     {
247         FooType* fn = foo;
248         test_b5<int &>(fn);
249     }
250     {
251         typedef TestClass Fn;
252         Fn cl(42);
253         test_b5<int&>(cl);
254         test_b5<int const&>(static_cast<Fn const&>(cl));
255         test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
256         test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
257 
258         test_b5<int&&>(static_cast<Fn &&>(cl));
259         test_b5<int const&&>(static_cast<Fn const&&>(cl));
260         test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
261         test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
262     }
263 }
264 
265 int main() {
266     bullet_one_two_tests();
267     bullet_three_four_tests();
268     bullet_five_tests();
269 }
270