1*5be45129SEric Fiselier //===----------------------------------------------------------------------===//
2*5be45129SEric Fiselier //
3*5be45129SEric Fiselier //                     The LLVM Compiler Infrastructure
4*5be45129SEric Fiselier //
5*5be45129SEric Fiselier // This file is dual licensed under the MIT and the University of Illinois Open
6*5be45129SEric Fiselier // Source Licenses. See LICENSE.TXT for details.
7*5be45129SEric Fiselier //
8*5be45129SEric Fiselier //===----------------------------------------------------------------------===//
9*5be45129SEric Fiselier 
10*5be45129SEric Fiselier // UNSUPPORTED: c++98, c++03, c++11, c++14
11*5be45129SEric Fiselier 
12*5be45129SEric Fiselier // <functional>
13*5be45129SEric Fiselier 
14*5be45129SEric Fiselier // template <class F, class ...Args>
15*5be45129SEric Fiselier // result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...);
16*5be45129SEric Fiselier 
17*5be45129SEric Fiselier /// C++14 [func.def] 20.9.0
18*5be45129SEric Fiselier /// (1) The following definitions apply to this Clause:
19*5be45129SEric Fiselier /// (2) A call signature is the name of a return type followed by a parenthesized
20*5be45129SEric Fiselier ///     comma-separated list of zero or more argument types.
21*5be45129SEric Fiselier /// (3) A callable type is a function object type (20.9) or a pointer to member.
22*5be45129SEric Fiselier /// (4) A callable object is an object of a callable type.
23*5be45129SEric Fiselier /// (5) A call wrapper type is a type that holds a callable object and supports
24*5be45129SEric Fiselier ///     a call operation that forwards to that object.
25*5be45129SEric Fiselier /// (6) A call wrapper is an object of a call wrapper type.
26*5be45129SEric Fiselier /// (7) A target object is the callable object held by a call wrapper.
27*5be45129SEric Fiselier 
28*5be45129SEric Fiselier /// C++14 [func.require] 20.9.1
29*5be45129SEric Fiselier ///
30*5be45129SEric Fiselier /// Define INVOKE (f, t1, t2, ..., tN) as follows:
31*5be45129SEric Fiselier ///   (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*5be45129SEric Fiselier ///   type T or a reference to an object of type T or a reference to an object of a type derived from T;
33*5be45129SEric Fiselier ///   (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*5be45129SEric Fiselier ///   the types described in the previous item;
35*5be45129SEric Fiselier ///   (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*5be45129SEric Fiselier ///   reference to an object of type T or a reference to an object of a type derived from T;
37*5be45129SEric Fiselier ///   (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*5be45129SEric Fiselier ///   described in the previous item;
39*5be45129SEric Fiselier ///   (1.5) — f(t1, t2, ..., tN) in all other cases.
40*5be45129SEric Fiselier 
41*5be45129SEric Fiselier #include <functional>
42*5be45129SEric Fiselier #include <type_traits>
43*5be45129SEric Fiselier #include <cassert>
44*5be45129SEric Fiselier 
45*5be45129SEric Fiselier struct NonCopyable {
46*5be45129SEric Fiselier     NonCopyable() {}
47*5be45129SEric Fiselier private:
48*5be45129SEric Fiselier     NonCopyable(NonCopyable const&) = delete;
49*5be45129SEric Fiselier     NonCopyable& operator=(NonCopyable const&) = delete;
50*5be45129SEric Fiselier };
51*5be45129SEric Fiselier 
52*5be45129SEric Fiselier struct TestClass {
53*5be45129SEric Fiselier     explicit TestClass(int x) : data(x) {}
54*5be45129SEric Fiselier 
55*5be45129SEric Fiselier     int& operator()(NonCopyable&&) & { return data; }
56*5be45129SEric Fiselier     int const& operator()(NonCopyable&&) const & { return data; }
57*5be45129SEric Fiselier     int volatile& operator()(NonCopyable&&) volatile & { return data; }
58*5be45129SEric Fiselier     int const volatile& operator()(NonCopyable&&) const volatile & { return data; }
59*5be45129SEric Fiselier 
60*5be45129SEric Fiselier     int&& operator()(NonCopyable&&) && { return std::move(data); }
61*5be45129SEric Fiselier     int const&& operator()(NonCopyable&&) const && { return std::move(data); }
62*5be45129SEric Fiselier     int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); }
63*5be45129SEric Fiselier     int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); }
64*5be45129SEric Fiselier 
65*5be45129SEric Fiselier     int data;
66*5be45129SEric Fiselier private:
67*5be45129SEric Fiselier     TestClass(TestClass const&) = delete;
68*5be45129SEric Fiselier     TestClass& operator=(TestClass const&) = delete;
69*5be45129SEric Fiselier };
70*5be45129SEric Fiselier 
71*5be45129SEric Fiselier struct DerivedFromTestClass : public TestClass {
72*5be45129SEric Fiselier     explicit DerivedFromTestClass(int x) : TestClass(x) {}
73*5be45129SEric Fiselier };
74*5be45129SEric Fiselier 
75*5be45129SEric Fiselier int& foo(NonCopyable&&) {
76*5be45129SEric Fiselier     static int data = 42;
77*5be45129SEric Fiselier     return data;
78*5be45129SEric Fiselier }
79*5be45129SEric Fiselier 
80*5be45129SEric Fiselier template <class Signature,  class Expect, class Functor>
81*5be45129SEric Fiselier void test_b12(Functor&& f) {
82*5be45129SEric Fiselier     // Create the callable object.
83*5be45129SEric Fiselier     typedef Signature TestClass::*ClassFunc;
84*5be45129SEric Fiselier     ClassFunc func_ptr = &TestClass::operator();
85*5be45129SEric Fiselier 
86*5be45129SEric Fiselier     // Create the dummy arg.
87*5be45129SEric Fiselier     NonCopyable arg;
88*5be45129SEric Fiselier 
89*5be45129SEric Fiselier     // Check that the deduced return type of invoke is what is expected.
90*5be45129SEric Fiselier     typedef decltype(
91*5be45129SEric Fiselier         std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg))
92*5be45129SEric Fiselier     ) DeducedReturnType;
93*5be45129SEric Fiselier     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
94*5be45129SEric Fiselier 
95*5be45129SEric Fiselier     // Check that result_of_t matches Expect.
96*5be45129SEric Fiselier     typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type
97*5be45129SEric Fiselier       ResultOfReturnType;
98*5be45129SEric Fiselier     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
99*5be45129SEric Fiselier 
100*5be45129SEric Fiselier     // Run invoke and check the return value.
101*5be45129SEric Fiselier     DeducedReturnType ret =
102*5be45129SEric Fiselier             std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg));
103*5be45129SEric Fiselier     assert(ret == 42);
104*5be45129SEric Fiselier }
105*5be45129SEric Fiselier 
106*5be45129SEric Fiselier template <class Expect, class Functor>
107*5be45129SEric Fiselier void test_b34(Functor&& f) {
108*5be45129SEric Fiselier     // Create the callable object.
109*5be45129SEric Fiselier     typedef int TestClass::*ClassFunc;
110*5be45129SEric Fiselier     ClassFunc func_ptr = &TestClass::data;
111*5be45129SEric Fiselier 
112*5be45129SEric Fiselier     // Check that the deduced return type of invoke is what is expected.
113*5be45129SEric Fiselier     typedef decltype(
114*5be45129SEric Fiselier         std::invoke(func_ptr, std::forward<Functor>(f))
115*5be45129SEric Fiselier     ) DeducedReturnType;
116*5be45129SEric Fiselier     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
117*5be45129SEric Fiselier 
118*5be45129SEric Fiselier     // Check that result_of_t matches Expect.
119*5be45129SEric Fiselier     typedef typename std::result_of<ClassFunc&&(Functor&&)>::type
120*5be45129SEric Fiselier             ResultOfReturnType;
121*5be45129SEric Fiselier     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
122*5be45129SEric Fiselier 
123*5be45129SEric Fiselier     // Run invoke and check the return value.
124*5be45129SEric Fiselier     DeducedReturnType ret =
125*5be45129SEric Fiselier             std::invoke(func_ptr, std::forward<Functor>(f));
126*5be45129SEric Fiselier     assert(ret == 42);
127*5be45129SEric Fiselier }
128*5be45129SEric Fiselier 
129*5be45129SEric Fiselier template <class Expect, class Functor>
130*5be45129SEric Fiselier void test_b5(Functor&& f) {
131*5be45129SEric Fiselier     NonCopyable arg;
132*5be45129SEric Fiselier 
133*5be45129SEric Fiselier     // Check that the deduced return type of invoke is what is expected.
134*5be45129SEric Fiselier     typedef decltype(
135*5be45129SEric Fiselier         std::invoke(std::forward<Functor>(f), std::move(arg))
136*5be45129SEric Fiselier     ) DeducedReturnType;
137*5be45129SEric Fiselier     static_assert((std::is_same<DeducedReturnType, Expect>::value), "");
138*5be45129SEric Fiselier 
139*5be45129SEric Fiselier     // Check that result_of_t matches Expect.
140*5be45129SEric Fiselier     typedef typename std::result_of<Functor&&(NonCopyable&&)>::type
141*5be45129SEric Fiselier             ResultOfReturnType;
142*5be45129SEric Fiselier     static_assert((std::is_same<ResultOfReturnType, Expect>::value), "");
143*5be45129SEric Fiselier 
144*5be45129SEric Fiselier     // Run invoke and check the return value.
145*5be45129SEric Fiselier     DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg));
146*5be45129SEric Fiselier     assert(ret == 42);
147*5be45129SEric Fiselier }
148*5be45129SEric Fiselier 
149*5be45129SEric Fiselier void bullet_one_two_tests() {
150*5be45129SEric Fiselier     {
151*5be45129SEric Fiselier         TestClass cl(42);
152*5be45129SEric Fiselier         test_b12<int&(NonCopyable&&) &, int&>(cl);
153*5be45129SEric Fiselier         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
154*5be45129SEric Fiselier         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
155*5be45129SEric Fiselier         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
156*5be45129SEric Fiselier 
157*5be45129SEric Fiselier         test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
158*5be45129SEric Fiselier         test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
159*5be45129SEric Fiselier         test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
160*5be45129SEric Fiselier         test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
161*5be45129SEric Fiselier     }
162*5be45129SEric Fiselier     {
163*5be45129SEric Fiselier         DerivedFromTestClass cl(42);
164*5be45129SEric Fiselier         test_b12<int&(NonCopyable&&) &, int&>(cl);
165*5be45129SEric Fiselier         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
166*5be45129SEric Fiselier         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
167*5be45129SEric Fiselier         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
168*5be45129SEric Fiselier 
169*5be45129SEric Fiselier         test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl));
170*5be45129SEric Fiselier         test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl));
171*5be45129SEric Fiselier         test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl));
172*5be45129SEric Fiselier         test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl));
173*5be45129SEric Fiselier     }
174*5be45129SEric Fiselier     {
175*5be45129SEric Fiselier         TestClass cl_obj(42);
176*5be45129SEric Fiselier         TestClass *cl = &cl_obj;
177*5be45129SEric Fiselier         test_b12<int&(NonCopyable&&) &, int&>(cl);
178*5be45129SEric Fiselier         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
179*5be45129SEric Fiselier         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
180*5be45129SEric Fiselier         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
181*5be45129SEric Fiselier     }
182*5be45129SEric Fiselier     {
183*5be45129SEric Fiselier         DerivedFromTestClass cl_obj(42);
184*5be45129SEric Fiselier         DerivedFromTestClass *cl = &cl_obj;
185*5be45129SEric Fiselier         test_b12<int&(NonCopyable&&) &, int&>(cl);
186*5be45129SEric Fiselier         test_b12<int const&(NonCopyable&&) const &, int const&>(cl);
187*5be45129SEric Fiselier         test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl);
188*5be45129SEric Fiselier         test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl);
189*5be45129SEric Fiselier     }
190*5be45129SEric Fiselier }
191*5be45129SEric Fiselier 
192*5be45129SEric Fiselier void bullet_three_four_tests() {
193*5be45129SEric Fiselier     {
194*5be45129SEric Fiselier         typedef TestClass Fn;
195*5be45129SEric Fiselier         Fn cl(42);
196*5be45129SEric Fiselier         test_b34<int&>(cl);
197*5be45129SEric Fiselier         test_b34<int const&>(static_cast<Fn const&>(cl));
198*5be45129SEric Fiselier         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
199*5be45129SEric Fiselier         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
200*5be45129SEric Fiselier 
201*5be45129SEric Fiselier         test_b34<int&&>(static_cast<Fn &&>(cl));
202*5be45129SEric Fiselier         test_b34<int const&&>(static_cast<Fn const&&>(cl));
203*5be45129SEric Fiselier         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
204*5be45129SEric Fiselier         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
205*5be45129SEric Fiselier     }
206*5be45129SEric Fiselier     {
207*5be45129SEric Fiselier         typedef DerivedFromTestClass Fn;
208*5be45129SEric Fiselier         Fn cl(42);
209*5be45129SEric Fiselier         test_b34<int&>(cl);
210*5be45129SEric Fiselier         test_b34<int const&>(static_cast<Fn const&>(cl));
211*5be45129SEric Fiselier         test_b34<int volatile&>(static_cast<Fn volatile&>(cl));
212*5be45129SEric Fiselier         test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl));
213*5be45129SEric Fiselier 
214*5be45129SEric Fiselier         test_b34<int&&>(static_cast<Fn &&>(cl));
215*5be45129SEric Fiselier         test_b34<int const&&>(static_cast<Fn const&&>(cl));
216*5be45129SEric Fiselier         test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl));
217*5be45129SEric Fiselier         test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
218*5be45129SEric Fiselier     }
219*5be45129SEric Fiselier     {
220*5be45129SEric Fiselier         typedef TestClass Fn;
221*5be45129SEric Fiselier         Fn cl_obj(42);
222*5be45129SEric Fiselier         Fn* cl = &cl_obj;
223*5be45129SEric Fiselier         test_b34<int&>(cl);
224*5be45129SEric Fiselier         test_b34<int const&>(static_cast<Fn const*>(cl));
225*5be45129SEric Fiselier         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
226*5be45129SEric Fiselier         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
227*5be45129SEric Fiselier     }
228*5be45129SEric Fiselier     {
229*5be45129SEric Fiselier         typedef DerivedFromTestClass Fn;
230*5be45129SEric Fiselier         Fn cl_obj(42);
231*5be45129SEric Fiselier         Fn* cl = &cl_obj;
232*5be45129SEric Fiselier         test_b34<int&>(cl);
233*5be45129SEric Fiselier         test_b34<int const&>(static_cast<Fn const*>(cl));
234*5be45129SEric Fiselier         test_b34<int volatile&>(static_cast<Fn volatile*>(cl));
235*5be45129SEric Fiselier         test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl));
236*5be45129SEric Fiselier     }
237*5be45129SEric Fiselier }
238*5be45129SEric Fiselier 
239*5be45129SEric Fiselier void bullet_five_tests() {
240*5be45129SEric Fiselier     using FooType = int&(NonCopyable&&);
241*5be45129SEric Fiselier     {
242*5be45129SEric Fiselier         FooType& fn = foo;
243*5be45129SEric Fiselier         test_b5<int &>(fn);
244*5be45129SEric Fiselier     }
245*5be45129SEric Fiselier     {
246*5be45129SEric Fiselier         FooType* fn = foo;
247*5be45129SEric Fiselier         test_b5<int &>(fn);
248*5be45129SEric Fiselier     }
249*5be45129SEric Fiselier     {
250*5be45129SEric Fiselier         typedef TestClass Fn;
251*5be45129SEric Fiselier         Fn cl(42);
252*5be45129SEric Fiselier         test_b5<int&>(cl);
253*5be45129SEric Fiselier         test_b5<int const&>(static_cast<Fn const&>(cl));
254*5be45129SEric Fiselier         test_b5<int volatile&>(static_cast<Fn volatile&>(cl));
255*5be45129SEric Fiselier         test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl));
256*5be45129SEric Fiselier 
257*5be45129SEric Fiselier         test_b5<int&&>(static_cast<Fn &&>(cl));
258*5be45129SEric Fiselier         test_b5<int const&&>(static_cast<Fn const&&>(cl));
259*5be45129SEric Fiselier         test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl));
260*5be45129SEric Fiselier         test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl));
261*5be45129SEric Fiselier     }
262*5be45129SEric Fiselier }
263*5be45129SEric Fiselier 
264*5be45129SEric Fiselier int main() {
265*5be45129SEric Fiselier     bullet_one_two_tests();
266*5be45129SEric Fiselier     bullet_three_four_tests();
267*5be45129SEric Fiselier     bullet_five_tests();
268*5be45129SEric Fiselier }
269