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 <cassert>
44
45 struct NonCopyable {
NonCopyableNonCopyable46 NonCopyable() {}
47 private:
48 NonCopyable(NonCopyable const&) = delete;
49 NonCopyable& operator=(NonCopyable const&) = delete;
50 };
51
52 struct TestClass {
TestClassTestClass53 explicit TestClass(int x) : data(x) {}
54
operator ()TestClass55 int& operator()(NonCopyable&&) & { return data; }
operator ()TestClass56 int const& operator()(NonCopyable&&) const & { return data; }
operator ()TestClass57 int volatile& operator()(NonCopyable&&) volatile & { return data; }
operator ()TestClass58 int const volatile& operator()(NonCopyable&&) const volatile & { return data; }
59
operator ()TestClass60 int&& operator()(NonCopyable&&) && { return std::move(data); }
operator ()TestClass61 int const&& operator()(NonCopyable&&) const && { return std::move(data); }
operator ()TestClass62 int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
operator ()TestClass63 int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }
64
65 int data;
66 private:
67 TestClass(TestClass const&) = delete;
68 TestClass& operator=(TestClass const&) = delete;
69 };
70
71 struct DerivedFromTestClass : public TestClass {
DerivedFromTestClassDerivedFromTestClass72 explicit DerivedFromTestClass(int x) : TestClass(x) {}
73 };
74
foo(NonCopyable &&)75 int& foo(NonCopyable&&) {
76 static int data = 42;
77 return data;
78 }
79
80 template <class Signature, class Expect, class Functor>
test_b12(Functor && f)81 void test_b12(Functor&& f) {
82 // Create the callable object.
83 typedef Signature TestClass::*ClassFunc;
84 ClassFunc func_ptr = &TestClass::operator();
85
86 // Create the dummy arg.
87 NonCopyable arg;
88
89 // Check that the deduced return type of invoke is what is expected.
90 typedef decltype(
91 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
92 ) DeducedReturnType;
93 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
94
95 // Check that result_of_t matches Expect.
96 typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
97 ResultOfReturnType;
98 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
99
100 // Run invoke and check the return value.
101 DeducedReturnType ret =
102 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
103 assert(ret == 42);
104 }
105
106 template <class Expect, class Functor>
test_b34(Functor && f)107 void test_b34(Functor&& f) {
108 // Create the callable object.
109 typedef int TestClass::*ClassFunc;
110 ClassFunc func_ptr = &TestClass::data;
111
112 // Check that the deduced return type of invoke is what is expected.
113 typedef decltype(
114 std::invoke(func_ptr, std::forward<Functor>(f))
115 ) DeducedReturnType;
116 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
117
118 // Check that result_of_t matches Expect.
119 typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
120 ResultOfReturnType;
121 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
122
123 // Run invoke and check the return value.
124 DeducedReturnType ret =
125 std::invoke(func_ptr, std::forward<Functor>(f));
126 assert(ret == 42);
127 }
128
129 template <class Expect, class Functor>
test_b5(Functor && f)130 void test_b5(Functor&& f) {
131 NonCopyable arg;
132
133 // Check that the deduced return type of invoke is what is expected.
134 typedef decltype(
135 std::invoke(std::forward<Functor>(f), std::move(arg))
136 ) DeducedReturnType;
137 static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
138
139 // Check that result_of_t matches Expect.
140 typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
141 ResultOfReturnType;
142 static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
143
144 // Run invoke and check the return value.
145 DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
146 assert(ret == 42);
147 }
148
bullet_one_two_tests()149 void bullet_one_two_tests() {
150 {
151 TestClass cl(42);
152 test_b12<int&(NonCopyable&&) &, int&>(cl);
153 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
154 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
155 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
156
157 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
158 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
159 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
160 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
161 }
162 {
163 DerivedFromTestClass cl(42);
164 test_b12<int&(NonCopyable&&) &, int&>(cl);
165 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
166 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
167 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
168
169 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
170 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
171 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
172 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
173 }
174 {
175 TestClass cl_obj(42);
176 TestClass *cl = &cl_obj;
177 test_b12<int&(NonCopyable&&) &, int&>(cl);
178 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
179 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
180 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
181 }
182 {
183 DerivedFromTestClass cl_obj(42);
184 DerivedFromTestClass *cl = &cl_obj;
185 test_b12<int&(NonCopyable&&) &, int&>(cl);
186 test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
187 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
188 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
189 }
190 }
191
bullet_three_four_tests()192 void bullet_three_four_tests() {
193 {
194 typedef TestClass Fn;
195 Fn cl(42);
196 test_b34<int&>(cl);
197 test_b34<int const&>(static_cast<Fn const&>(cl));
198 test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
199 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
200
201 test_b34<int&&>(static_cast<Fn &&>(cl));
202 test_b34<int const&&>(static_cast<Fn const&&>(cl));
203 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
204 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
205 }
206 {
207 typedef DerivedFromTestClass Fn;
208 Fn cl(42);
209 test_b34<int&>(cl);
210 test_b34<int const&>(static_cast<Fn const&>(cl));
211 test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
212 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
213
214 test_b34<int&&>(static_cast<Fn &&>(cl));
215 test_b34<int const&&>(static_cast<Fn const&&>(cl));
216 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
217 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
218 }
219 {
220 typedef TestClass Fn;
221 Fn cl_obj(42);
222 Fn* cl = &cl_obj;
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 {
229 typedef DerivedFromTestClass Fn;
230 Fn cl_obj(42);
231 Fn* cl = &cl_obj;
232 test_b34<int&>(cl);
233 test_b34<int const&>(static_cast<Fn const*>(cl));
234 test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
235 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
236 }
237 }
238
bullet_five_tests()239 void bullet_five_tests() {
240 using FooType = int&(NonCopyable&&);
241 {
242 FooType& fn = foo;
243 test_b5<int &>(fn);
244 }
245 {
246 FooType* fn = foo;
247 test_b5<int &>(fn);
248 }
249 {
250 typedef TestClass Fn;
251 Fn cl(42);
252 test_b5<int&>(cl);
253 test_b5<int const&>(static_cast<Fn const&>(cl));
254 test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
255 test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
256
257 test_b5<int&&>(static_cast<Fn &&>(cl));
258 test_b5<int const&&>(static_cast<Fn const&&>(cl));
259 test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
260 test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
261 }
262 }
263
main()264 int main() {
265 bullet_one_two_tests();
266 bullet_three_four_tests();
267 bullet_five_tests();
268 }
269