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 { 46 NonCopyable() {} 47 private: 48 NonCopyable(NonCopyable const&) = delete; 49 NonCopyable& operator=(NonCopyable const&) = delete; 50 }; 51 52 struct TestClass { 53 explicit TestClass(int x) : data(x) {} 54 55 int& operator()(NonCopyable&&) & { return data; } 56 int const& operator()(NonCopyable&&) const & { return data; } 57 int volatile& operator()(NonCopyable&&) volatile & { return data; } 58 int const volatile& operator()(NonCopyable&&) const volatile & { return data; } 59 60 int&& operator()(NonCopyable&&) && { return std::move(data); } 61 int const&& operator()(NonCopyable&&) const && { return std::move(data); } 62 int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); } 63 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 { 72 explicit DerivedFromTestClass(int x) : TestClass(x) {} 73 }; 74 75 int& foo(NonCopyable&&) { 76 static int data = 42; 77 return data; 78 } 79 80 template <class Signature, class Expect, class Functor> 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> 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> 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 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 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 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 264 int main() { 265 bullet_one_two_tests(); 266 bullet_three_four_tests(); 267 bullet_five_tests(); 268 } 269