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 <utility> // for std::move 44 #include <cassert> 45 46 struct NonCopyable { 47 NonCopyable() {} 48 private: 49 NonCopyable(NonCopyable const&) = delete; 50 NonCopyable& operator=(NonCopyable const&) = delete; 51 }; 52 53 struct TestClass { 54 explicit TestClass(int x) : data(x) {} 55 56 int& operator()(NonCopyable&&) & { return data; } 57 int const& operator()(NonCopyable&&) const & { return data; } 58 int volatile& operator()(NonCopyable&&) volatile & { return data; } 59 int const volatile& operator()(NonCopyable&&) const volatile & { return data; } 60 61 int&& operator()(NonCopyable&&) && { return std::move(data); } 62 int const&& operator()(NonCopyable&&) const && { return std::move(data); } 63 int volatile&& operator()(NonCopyable&&) volatile && { return std::move(data); } 64 int const volatile&& operator()(NonCopyable&&) const volatile && { return std::move(data); } 65 66 int data; 67 private: 68 TestClass(TestClass const&) = delete; 69 TestClass& operator=(TestClass const&) = delete; 70 }; 71 72 struct DerivedFromTestClass : public TestClass { 73 explicit DerivedFromTestClass(int x) : TestClass(x) {} 74 }; 75 76 int& foo(NonCopyable&&) { 77 static int data = 42; 78 return data; 79 } 80 81 template <class Signature, class Expect, class Functor> 82 void test_b12(Functor&& f) { 83 // Create the callable object. 84 typedef Signature TestClass::*ClassFunc; 85 ClassFunc func_ptr = &TestClass::operator(); 86 87 // Create the dummy arg. 88 NonCopyable arg; 89 90 // Check that the deduced return type of invoke is what is expected. 91 typedef decltype( 92 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg)) 93 ) DeducedReturnType; 94 static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); 95 96 // Check that result_of_t matches Expect. 97 typedef typename std::result_of<ClassFunc&&(Functor&&, NonCopyable&&)>::type 98 ResultOfReturnType; 99 static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); 100 101 // Run invoke and check the return value. 102 DeducedReturnType ret = 103 std::invoke(func_ptr, std::forward<Functor>(f), std::move(arg)); 104 assert(ret == 42); 105 } 106 107 template <class Expect, class Functor> 108 void test_b34(Functor&& f) { 109 // Create the callable object. 110 typedef int TestClass::*ClassFunc; 111 ClassFunc func_ptr = &TestClass::data; 112 113 // Check that the deduced return type of invoke is what is expected. 114 typedef decltype( 115 std::invoke(func_ptr, std::forward<Functor>(f)) 116 ) DeducedReturnType; 117 static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); 118 119 // Check that result_of_t matches Expect. 120 typedef typename std::result_of<ClassFunc&&(Functor&&)>::type 121 ResultOfReturnType; 122 static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); 123 124 // Run invoke and check the return value. 125 DeducedReturnType ret = 126 std::invoke(func_ptr, std::forward<Functor>(f)); 127 assert(ret == 42); 128 } 129 130 template <class Expect, class Functor> 131 void test_b5(Functor&& f) { 132 NonCopyable arg; 133 134 // Check that the deduced return type of invoke is what is expected. 135 typedef decltype( 136 std::invoke(std::forward<Functor>(f), std::move(arg)) 137 ) DeducedReturnType; 138 static_assert((std::is_same<DeducedReturnType, Expect>::value), ""); 139 140 // Check that result_of_t matches Expect. 141 typedef typename std::result_of<Functor&&(NonCopyable&&)>::type 142 ResultOfReturnType; 143 static_assert((std::is_same<ResultOfReturnType, Expect>::value), ""); 144 145 // Run invoke and check the return value. 146 DeducedReturnType ret = std::invoke(std::forward<Functor>(f), std::move(arg)); 147 assert(ret == 42); 148 } 149 150 void bullet_one_two_tests() { 151 { 152 TestClass cl(42); 153 test_b12<int&(NonCopyable&&) &, int&>(cl); 154 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 155 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 156 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 157 158 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); 159 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); 160 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl)); 161 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl)); 162 } 163 { 164 DerivedFromTestClass cl(42); 165 test_b12<int&(NonCopyable&&) &, int&>(cl); 166 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 167 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 168 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 169 170 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); 171 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); 172 test_b12<int volatile&&(NonCopyable&&) volatile &&, int volatile&&>(std::move(cl)); 173 test_b12<int const volatile&&(NonCopyable&&) const volatile &&, int const volatile&&>(std::move(cl)); 174 } 175 { 176 TestClass cl_obj(42); 177 std::reference_wrapper<TestClass> cl(cl_obj); 178 test_b12<int&(NonCopyable&&) &, int&>(cl); 179 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 180 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 181 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 182 183 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); 184 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); 185 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl)); 186 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl)); 187 } 188 { 189 DerivedFromTestClass cl_obj(42); 190 std::reference_wrapper<DerivedFromTestClass> cl(cl_obj); 191 test_b12<int&(NonCopyable&&) &, int&>(cl); 192 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 193 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 194 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 195 196 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); 197 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); 198 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(std::move(cl)); 199 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(std::move(cl)); 200 } 201 { 202 TestClass cl_obj(42); 203 TestClass *cl = &cl_obj; 204 test_b12<int&(NonCopyable&&) &, int&>(cl); 205 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 206 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 207 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 208 } 209 { 210 DerivedFromTestClass cl_obj(42); 211 DerivedFromTestClass *cl = &cl_obj; 212 test_b12<int&(NonCopyable&&) &, int&>(cl); 213 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 214 test_b12<int volatile&(NonCopyable&&) volatile &, int volatile&>(cl); 215 test_b12<int const volatile&(NonCopyable&&) const volatile &, int const volatile&>(cl); 216 } 217 } 218 219 void bullet_three_four_tests() { 220 { 221 typedef TestClass Fn; 222 Fn cl(42); 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 test_b34<int&&>(static_cast<Fn &&>(cl)); 229 test_b34<int const&&>(static_cast<Fn const&&>(cl)); 230 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl)); 231 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); 232 } 233 { 234 typedef DerivedFromTestClass Fn; 235 Fn cl(42); 236 test_b34<int&>(cl); 237 test_b34<int const&>(static_cast<Fn const&>(cl)); 238 test_b34<int volatile&>(static_cast<Fn volatile&>(cl)); 239 test_b34<int const volatile&>(static_cast<Fn const volatile &>(cl)); 240 241 test_b34<int&&>(static_cast<Fn &&>(cl)); 242 test_b34<int const&&>(static_cast<Fn const&&>(cl)); 243 test_b34<int volatile&&>(static_cast<Fn volatile&&>(cl)); 244 test_b34<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); 245 } 246 { 247 typedef TestClass Fn; 248 Fn cl(42); 249 test_b34<int&>(std::reference_wrapper<Fn>(cl)); 250 test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); 251 test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl)); 252 test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl)); 253 } 254 { 255 typedef DerivedFromTestClass Fn; 256 Fn cl(42); 257 test_b34<int&>(std::reference_wrapper<Fn>(cl)); 258 test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); 259 test_b34<int volatile&>(std::reference_wrapper<Fn volatile>(cl)); 260 test_b34<int const volatile&>(std::reference_wrapper<Fn const volatile>(cl)); 261 } 262 { 263 typedef TestClass Fn; 264 Fn cl_obj(42); 265 Fn* cl = &cl_obj; 266 test_b34<int&>(cl); 267 test_b34<int const&>(static_cast<Fn const*>(cl)); 268 test_b34<int volatile&>(static_cast<Fn volatile*>(cl)); 269 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl)); 270 } 271 { 272 typedef DerivedFromTestClass Fn; 273 Fn cl_obj(42); 274 Fn* cl = &cl_obj; 275 test_b34<int&>(cl); 276 test_b34<int const&>(static_cast<Fn const*>(cl)); 277 test_b34<int volatile&>(static_cast<Fn volatile*>(cl)); 278 test_b34<int const volatile&>(static_cast<Fn const volatile *>(cl)); 279 } 280 } 281 282 void bullet_five_tests() { 283 using FooType = int&(NonCopyable&&); 284 { 285 FooType& fn = foo; 286 test_b5<int &>(fn); 287 } 288 { 289 FooType* fn = foo; 290 test_b5<int &>(fn); 291 } 292 { 293 typedef TestClass Fn; 294 Fn cl(42); 295 test_b5<int&>(cl); 296 test_b5<int const&>(static_cast<Fn const&>(cl)); 297 test_b5<int volatile&>(static_cast<Fn volatile&>(cl)); 298 test_b5<int const volatile&>(static_cast<Fn const volatile &>(cl)); 299 300 test_b5<int&&>(static_cast<Fn &&>(cl)); 301 test_b5<int const&&>(static_cast<Fn const&&>(cl)); 302 test_b5<int volatile&&>(static_cast<Fn volatile&&>(cl)); 303 test_b5<int const volatile&&>(static_cast<Fn const volatile&&>(cl)); 304 } 305 } 306 307 int main() { 308 bullet_one_two_tests(); 309 bullet_three_four_tests(); 310 bullet_five_tests(); 311 } 312