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