15be45129SEric Fiselier //===----------------------------------------------------------------------===// 25be45129SEric Fiselier // 35be45129SEric Fiselier // The LLVM Compiler Infrastructure 45be45129SEric Fiselier // 55be45129SEric Fiselier // This file is dual licensed under the MIT and the University of Illinois Open 65be45129SEric Fiselier // Source Licenses. See LICENSE.TXT for details. 75be45129SEric Fiselier // 85be45129SEric Fiselier //===----------------------------------------------------------------------===// 95be45129SEric Fiselier 105be45129SEric Fiselier // UNSUPPORTED: c++98, c++03, c++11, c++14 115be45129SEric Fiselier 125be45129SEric Fiselier // <functional> 135be45129SEric Fiselier 145be45129SEric Fiselier // template <class F, class ...Args> 155be45129SEric Fiselier // result_of_t<F&&(Args&&...)> invoke(F&&, Args&&...); 165be45129SEric Fiselier 175be45129SEric Fiselier /// C++14 [func.def] 20.9.0 185be45129SEric Fiselier /// (1) The following definitions apply to this Clause: 195be45129SEric Fiselier /// (2) A call signature is the name of a return type followed by a parenthesized 205be45129SEric Fiselier /// comma-separated list of zero or more argument types. 215be45129SEric Fiselier /// (3) A callable type is a function object type (20.9) or a pointer to member. 225be45129SEric Fiselier /// (4) A callable object is an object of a callable type. 235be45129SEric Fiselier /// (5) A call wrapper type is a type that holds a callable object and supports 245be45129SEric Fiselier /// a call operation that forwards to that object. 255be45129SEric Fiselier /// (6) A call wrapper is an object of a call wrapper type. 265be45129SEric Fiselier /// (7) A target object is the callable object held by a call wrapper. 275be45129SEric Fiselier 285be45129SEric Fiselier /// C++14 [func.require] 20.9.1 295be45129SEric Fiselier /// 305be45129SEric Fiselier /// Define INVOKE (f, t1, t2, ..., tN) as follows: 3116270a0bSEric 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 325be45129SEric Fiselier /// type T or a reference to an object of type T or a reference to an object of a type derived from T; 3316270a0bSEric 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 345be45129SEric Fiselier /// the types described in the previous item; 3516270a0bSEric 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 365be45129SEric Fiselier /// reference to an object of type T or a reference to an object of a type derived from T; 3716270a0bSEric 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 385be45129SEric Fiselier /// described in the previous item; 3916270a0bSEric Fiselier /// (1.5) - f(t1, t2, ..., tN) in all other cases. 405be45129SEric Fiselier 415be45129SEric Fiselier #include <functional> 425be45129SEric Fiselier #include <type_traits> 43d1180f4aSMarshall Clow #include <utility> // for std::move 445be45129SEric Fiselier #include <cassert> 455be45129SEric Fiselier 465be45129SEric Fiselier struct NonCopyable { 475be45129SEric Fiselier NonCopyable() {} 485be45129SEric Fiselier private: 495be45129SEric Fiselier NonCopyable(NonCopyable const&) = delete; 505be45129SEric Fiselier NonCopyable& operator=(NonCopyable const&) = delete; 515be45129SEric Fiselier }; 525be45129SEric Fiselier 535be45129SEric Fiselier struct TestClass { 545be45129SEric Fiselier explicit TestClass(int x) : data(x) {} 555be45129SEric Fiselier 565be45129SEric Fiselier int& operator()(NonCopyable&&) & { return data; } 575be45129SEric Fiselier int const& operator()(NonCopyable&&) const & { return data; } 585be45129SEric Fiselier int volatile& operator()(NonCopyable&&) volatile & { return data; } 595be45129SEric Fiselier int const volatile& operator()(NonCopyable&&) const volatile & { return data; } 605be45129SEric Fiselier 615be45129SEric Fiselier int&& operator()(NonCopyable&&) && { return std::move(data); } 625be45129SEric Fiselier int const&& operator()(NonCopyable&&) const && { return std::move(data); } 635be45129SEric Fiselier int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); } 645be45129SEric Fiselier int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); } 655be45129SEric Fiselier 665be45129SEric Fiselier int data; 675be45129SEric Fiselier private: 685be45129SEric Fiselier TestClass(TestClass const&) = delete; 695be45129SEric Fiselier TestClass& operator=(TestClass const&) = delete; 705be45129SEric Fiselier }; 715be45129SEric Fiselier 725be45129SEric Fiselier struct DerivedFromTestClass : public TestClass { 735be45129SEric Fiselier explicit DerivedFromTestClass(int x) : TestClass(x) {} 745be45129SEric Fiselier }; 755be45129SEric Fiselier 765be45129SEric Fiselier int& foo(NonCopyable&&) { 775be45129SEric Fiselier static int data = 42; 785be45129SEric Fiselier return data; 795be45129SEric Fiselier } 805be45129SEric Fiselier 815be45129SEric Fiselier template <class Signature, class Expect, class Functor> 825be45129SEric Fiselier void test_b12(Functor&& f) { 835be45129SEric Fiselier // Create the callable object. 845be45129SEric Fiselier typedef Signature TestClass::*ClassFunc; 855be45129SEric Fiselier ClassFunc func_ptr = &TestClass::operator(); 865be45129SEric Fiselier 875be45129SEric Fiselier // Create the dummy arg. 885be45129SEric Fiselier NonCopyable arg; 895be45129SEric Fiselier 905be45129SEric Fiselier // Check that the deduced return type of invoke is what is expected. 915be45129SEric Fiselier typedef decltype( 925be45129SEric Fiselier std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg)) 935be45129SEric Fiselier ) DeducedReturnType; 945be45129SEric Fiselier static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); 955be45129SEric Fiselier 965be45129SEric Fiselier // Check that result_of_t matches Expect. 975be45129SEric Fiselier typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type 985be45129SEric Fiselier ResultOfReturnType; 995be45129SEric Fiselier static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); 1005be45129SEric Fiselier 1015be45129SEric Fiselier // Run invoke and check the return value. 1025be45129SEric Fiselier DeducedReturnType ret = 1035be45129SEric Fiselier std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg)); 1045be45129SEric Fiselier assert(ret == 42); 1055be45129SEric Fiselier } 1065be45129SEric Fiselier 1075be45129SEric Fiselier template <class Expect, class Functor> 1085be45129SEric Fiselier void test_b34(Functor&& f) { 1095be45129SEric Fiselier // Create the callable object. 1105be45129SEric Fiselier typedef int TestClass::*ClassFunc; 1115be45129SEric Fiselier ClassFunc func_ptr = &TestClass::data; 1125be45129SEric Fiselier 1135be45129SEric Fiselier // Check that the deduced return type of invoke is what is expected. 1145be45129SEric Fiselier typedef decltype( 1155be45129SEric Fiselier std::invoke(func_ptr, std::forward<Functor>(f)) 1165be45129SEric Fiselier ) DeducedReturnType; 1175be45129SEric Fiselier static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); 1185be45129SEric Fiselier 1195be45129SEric Fiselier // Check that result_of_t matches Expect. 1205be45129SEric Fiselier typedef typename std::result_of<ClassFunc&&(Functor&&)>::type 1215be45129SEric Fiselier ResultOfReturnType; 1225be45129SEric Fiselier static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); 1235be45129SEric Fiselier 1245be45129SEric Fiselier // Run invoke and check the return value. 1255be45129SEric Fiselier DeducedReturnType ret = 1265be45129SEric Fiselier std::invoke(func_ptr, std::forward<Functor>(f)); 1275be45129SEric Fiselier assert(ret == 42); 1285be45129SEric Fiselier } 1295be45129SEric Fiselier 1305be45129SEric Fiselier template <class Expect, class Functor> 1315be45129SEric Fiselier void test_b5(Functor&& f) { 1325be45129SEric Fiselier NonCopyable arg; 1335be45129SEric Fiselier 1345be45129SEric Fiselier // Check that the deduced return type of invoke is what is expected. 1355be45129SEric Fiselier typedef decltype( 1365be45129SEric Fiselier std::invoke(std::forward<Functor>(f), std::move(arg)) 1375be45129SEric Fiselier ) DeducedReturnType; 1385be45129SEric Fiselier static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); 1395be45129SEric Fiselier 1405be45129SEric Fiselier // Check that result_of_t matches Expect. 1415be45129SEric Fiselier typedef typename std::result_of<Functor&&(NonCopyable&&)>::type 1425be45129SEric Fiselier ResultOfReturnType; 1435be45129SEric Fiselier static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); 1445be45129SEric Fiselier 1455be45129SEric Fiselier // Run invoke and check the return value. 1465be45129SEric Fiselier DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg)); 1475be45129SEric Fiselier assert(ret == 42); 1485be45129SEric Fiselier } 1495be45129SEric Fiselier 1505be45129SEric Fiselier void bullet_one_two_tests() { 1515be45129SEric Fiselier { 1525be45129SEric Fiselier TestClass cl(42); 1535be45129SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(cl); 1545be45129SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 1555be45129SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 1565be45129SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 1575be45129SEric Fiselier 1585be45129SEric Fiselier test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); 1595be45129SEric Fiselier test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); 1605be45129SEric Fiselier test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl)); 1615be45129SEric Fiselier test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl)); 1625be45129SEric Fiselier } 1635be45129SEric Fiselier { 1645be45129SEric Fiselier DerivedFromTestClass cl(42); 1655be45129SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(cl); 1665be45129SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 1675be45129SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 1685be45129SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 1695be45129SEric Fiselier 1705be45129SEric Fiselier test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); 1715be45129SEric Fiselier test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); 1725be45129SEric Fiselier test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl)); 1735be45129SEric Fiselier test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl)); 1745be45129SEric Fiselier } 1755be45129SEric Fiselier { 1765be45129SEric Fiselier TestClass cl_obj(42); 177*2152fd76SEric Fiselier std::reference_wrapper<TestClass> cl(cl_obj); 178*2152fd76SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(cl); 179*2152fd76SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 180*2152fd76SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 181*2152fd76SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 182*2152fd76SEric Fiselier 183*2152fd76SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); 184*2152fd76SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); 185*2152fd76SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl)); 186*2152fd76SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl)); 187*2152fd76SEric Fiselier } 188*2152fd76SEric Fiselier { 189*2152fd76SEric Fiselier DerivedFromTestClass cl_obj(42); 190*2152fd76SEric Fiselier std::reference_wrapper<DerivedFromTestClass> cl(cl_obj); 191*2152fd76SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(cl); 192*2152fd76SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 193*2152fd76SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 194*2152fd76SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 195*2152fd76SEric Fiselier 196*2152fd76SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); 197*2152fd76SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); 198*2152fd76SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl)); 199*2152fd76SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl)); 200*2152fd76SEric Fiselier } 201*2152fd76SEric Fiselier { 202*2152fd76SEric Fiselier TestClass cl_obj(42); 2035be45129SEric Fiselier TestClass *cl = &cl_obj; 2045be45129SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(cl); 2055be45129SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 2065be45129SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 2075be45129SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 2085be45129SEric Fiselier } 2095be45129SEric Fiselier { 2105be45129SEric Fiselier DerivedFromTestClass cl_obj(42); 2115be45129SEric Fiselier DerivedFromTestClass *cl = &cl_obj; 2125be45129SEric Fiselier test_b12<int&(NonCopyable&&) &, int&>(cl); 2135be45129SEric Fiselier test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 2145be45129SEric Fiselier test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 2155be45129SEric Fiselier test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 2165be45129SEric Fiselier } 2175be45129SEric Fiselier } 2185be45129SEric Fiselier 2195be45129SEric Fiselier void bullet_three_four_tests() { 2205be45129SEric Fiselier { 2215be45129SEric Fiselier typedef TestClass Fn; 2225be45129SEric Fiselier Fn cl(42); 2235be45129SEric Fiselier test_b34<int&>(cl); 2245be45129SEric Fiselier test_b34<int const&>(static_cast<Fn const&>(cl)); 2255be45129SEric Fiselier test_b34<int volatile&>(static_cast<Fn volatile&>(cl)); 2265be45129SEric Fiselier test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl)); 2275be45129SEric Fiselier 2285be45129SEric Fiselier test_b34<int&&>(static_cast<Fn &&>(cl)); 2295be45129SEric Fiselier test_b34<int const&&>(static_cast<Fn const&&>(cl)); 2305be45129SEric Fiselier test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl)); 2315be45129SEric Fiselier test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); 2325be45129SEric Fiselier } 2335be45129SEric Fiselier { 2345be45129SEric Fiselier typedef DerivedFromTestClass Fn; 2355be45129SEric Fiselier Fn cl(42); 2365be45129SEric Fiselier test_b34<int&>(cl); 2375be45129SEric Fiselier test_b34<int const&>(static_cast<Fn const&>(cl)); 2385be45129SEric Fiselier test_b34<int volatile&>(static_cast<Fn volatile&>(cl)); 2395be45129SEric Fiselier test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl)); 2405be45129SEric Fiselier 2415be45129SEric Fiselier test_b34<int&&>(static_cast<Fn &&>(cl)); 2425be45129SEric Fiselier test_b34<int const&&>(static_cast<Fn const&&>(cl)); 2435be45129SEric Fiselier test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl)); 2445be45129SEric Fiselier test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); 2455be45129SEric Fiselier } 2465be45129SEric Fiselier { 2475be45129SEric Fiselier typedef TestClass Fn; 248*2152fd76SEric Fiselier Fn cl(42); 249*2152fd76SEric Fiselier test_b34<int&>(std::reference_wrapper<Fn>(cl)); 250*2152fd76SEric Fiselier test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); 251*2152fd76SEric Fiselier test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl)); 252*2152fd76SEric Fiselier test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl)); 253*2152fd76SEric Fiselier } 254*2152fd76SEric Fiselier { 255*2152fd76SEric Fiselier typedef DerivedFromTestClass Fn; 256*2152fd76SEric Fiselier Fn cl(42); 257*2152fd76SEric Fiselier test_b34<int&>(std::reference_wrapper<Fn>(cl)); 258*2152fd76SEric Fiselier test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); 259*2152fd76SEric Fiselier test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl)); 260*2152fd76SEric Fiselier test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl)); 261*2152fd76SEric Fiselier } 262*2152fd76SEric Fiselier { 263*2152fd76SEric Fiselier typedef TestClass Fn; 2645be45129SEric Fiselier Fn cl_obj(42); 2655be45129SEric Fiselier Fn* cl = &cl_obj; 2665be45129SEric Fiselier test_b34<int&>(cl); 2675be45129SEric Fiselier test_b34<int const&>(static_cast<Fn const*>(cl)); 2685be45129SEric Fiselier test_b34<int volatile&>(static_cast<Fn volatile*>(cl)); 2695be45129SEric Fiselier test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl)); 2705be45129SEric Fiselier } 2715be45129SEric Fiselier { 2725be45129SEric Fiselier typedef DerivedFromTestClass Fn; 2735be45129SEric Fiselier Fn cl_obj(42); 2745be45129SEric Fiselier Fn* cl = &cl_obj; 2755be45129SEric Fiselier test_b34<int&>(cl); 2765be45129SEric Fiselier test_b34<int const&>(static_cast<Fn const*>(cl)); 2775be45129SEric Fiselier test_b34<int volatile&>(static_cast<Fn volatile*>(cl)); 2785be45129SEric Fiselier test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl)); 2795be45129SEric Fiselier } 2805be45129SEric Fiselier } 2815be45129SEric Fiselier 2825be45129SEric Fiselier void bullet_five_tests() { 2835be45129SEric Fiselier using FooType = int&(NonCopyable&&); 2845be45129SEric Fiselier { 2855be45129SEric Fiselier FooType& fn = foo; 2865be45129SEric Fiselier test_b5<int &>(fn); 2875be45129SEric Fiselier } 2885be45129SEric Fiselier { 2895be45129SEric Fiselier FooType* fn = foo; 2905be45129SEric Fiselier test_b5<int &>(fn); 2915be45129SEric Fiselier } 2925be45129SEric Fiselier { 2935be45129SEric Fiselier typedef TestClass Fn; 2945be45129SEric Fiselier Fn cl(42); 2955be45129SEric Fiselier test_b5<int&>(cl); 2965be45129SEric Fiselier test_b5<int const&>(static_cast<Fn const&>(cl)); 2975be45129SEric Fiselier test_b5<int volatile&>(static_cast<Fn volatile&>(cl)); 2985be45129SEric Fiselier test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl)); 2995be45129SEric Fiselier 3005be45129SEric Fiselier test_b5<int&&>(static_cast<Fn &&>(cl)); 3015be45129SEric Fiselier test_b5<int const&&>(static_cast<Fn const&&>(cl)); 3025be45129SEric Fiselier test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl)); 3035be45129SEric Fiselier test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); 3045be45129SEric Fiselier } 3055be45129SEric Fiselier } 3065be45129SEric Fiselier 3075be45129SEric Fiselier int main() { 3085be45129SEric Fiselier bullet_one_two_tests(); 3095be45129SEric Fiselier bullet_three_four_tests(); 3105be45129SEric Fiselier bullet_five_tests(); 3115be45129SEric Fiselier } 312