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