1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 11 // <functional> 12 13 // template<class F, class... Args> 14 // constexpr // constexpr in C++20 15 // invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) 16 // noexcept(is_nothrow_invocable_v<_Fn, _Args...>); 17 18 /// C++14 [func.def] 20.9.0 19 /// (1) The following definitions apply to this Clause: 20 /// (2) A call signature is the name of a return type followed by a parenthesized 21 /// comma-separated list of zero or more argument types. 22 /// (3) A callable type is a function object type (20.9) or a pointer to member. 23 /// (4) A callable object is an object of a callable type. 24 /// (5) A call wrapper type is a type that holds a callable object and supports 25 /// a call operation that forwards to that object. 26 /// (6) A call wrapper is an object of a call wrapper type. 27 /// (7) A target object is the callable object held by a call wrapper. 28 29 /// C++14 [func.require] 20.9.1 30 /// 31 /// Define INVOKE (f, t1, t2, ..., tN) as follows: 32 /// (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 /// type T or a reference to an object of type T or a reference to an object of a type derived from T; 34 /// (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 /// the types described in the previous item; 36 /// (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 /// reference to an object of type T or a reference to an object of a type derived from T; 38 /// (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 /// described in the previous item; 40 /// (1.5) - f(t1, t2, ..., tN) in all other cases. 41 42 #include <functional> 43 #include <type_traits> 44 #include <utility> // for std::move 45 #include <cassert> 46 47 #include "test_macros.h" 48 49 struct NonCopyable { 50 constexpr NonCopyable() {} 51 private: 52 NonCopyable(NonCopyable const&) = delete; 53 NonCopyable& operator=(NonCopyable const&) = delete; 54 }; 55 56 struct TestClass { 57 constexpr explicit TestClass(int x) : data(x) {} 58 59 constexpr int& operator()(NonCopyable&&) & { return data; } 60 constexpr int const& operator()(NonCopyable&&) const & { return data; } 61 62 constexpr int&& operator()(NonCopyable&&) && { return std::move(data); } 63 constexpr int const&& operator()(NonCopyable&&) const && { 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 constexpr explicit DerivedFromTestClass(int x) : TestClass(x) {} 73 }; 74 75 static constexpr int data = 42; 76 constexpr const int& foo(NonCopyable&&) { 77 return data; 78 } 79 80 template <class Signature, class Expect, class Functor> 81 constexpr 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 constexpr 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 constexpr 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 constexpr bool 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 155 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); 156 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); 157 } 158 { 159 DerivedFromTestClass cl(42); 160 test_b12<int&(NonCopyable&&) &, int&>(cl); 161 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 162 163 test_b12<int&&(NonCopyable&&) &&, int&&>(std::move(cl)); 164 test_b12<int const&&(NonCopyable&&) const &&, int const&&>(std::move(cl)); 165 } 166 { 167 TestClass cl_obj(42); 168 std::reference_wrapper<TestClass> cl(cl_obj); 169 test_b12<int&(NonCopyable&&) &, int&>(cl); 170 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 171 172 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); 173 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); 174 } 175 { 176 DerivedFromTestClass cl_obj(42); 177 std::reference_wrapper<DerivedFromTestClass> cl(cl_obj); 178 test_b12<int&(NonCopyable&&) &, int&>(cl); 179 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 180 181 test_b12<int&(NonCopyable&&) &, int&>(std::move(cl)); 182 test_b12<int const&(NonCopyable&&) const &, int const&>(std::move(cl)); 183 } 184 { 185 TestClass cl_obj(42); 186 TestClass *cl = &cl_obj; 187 test_b12<int&(NonCopyable&&) &, int&>(cl); 188 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 189 } 190 { 191 DerivedFromTestClass cl_obj(42); 192 DerivedFromTestClass *cl = &cl_obj; 193 test_b12<int&(NonCopyable&&) &, int&>(cl); 194 test_b12<int const&(NonCopyable&&) const &, int const&>(cl); 195 } 196 return true; 197 } 198 199 constexpr bool bullet_three_four_tests() { 200 { 201 typedef TestClass Fn; 202 Fn cl(42); 203 test_b34<int&>(cl); 204 test_b34<int const&>(static_cast<Fn const&>(cl)); 205 206 test_b34<int&&>(static_cast<Fn &&>(cl)); 207 test_b34<int const&&>(static_cast<Fn const&&>(cl)); 208 } 209 { 210 typedef DerivedFromTestClass Fn; 211 Fn cl(42); 212 test_b34<int&>(cl); 213 test_b34<int const&>(static_cast<Fn const&>(cl)); 214 215 test_b34<int&&>(static_cast<Fn &&>(cl)); 216 test_b34<int const&&>(static_cast<Fn const&&>(cl)); 217 } 218 { 219 typedef TestClass Fn; 220 Fn cl(42); 221 test_b34<int&>(std::reference_wrapper<Fn>(cl)); 222 test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); 223 } 224 { 225 typedef DerivedFromTestClass Fn; 226 Fn cl(42); 227 test_b34<int&>(std::reference_wrapper<Fn>(cl)); 228 test_b34<int const&>(std::reference_wrapper<Fn const>(cl)); 229 } 230 { 231 typedef TestClass Fn; 232 Fn cl_obj(42); 233 Fn* cl = &cl_obj; 234 test_b34<int&>(cl); 235 test_b34<int const&>(static_cast<Fn const*>(cl)); 236 } 237 { 238 typedef DerivedFromTestClass Fn; 239 Fn cl_obj(42); 240 Fn* cl = &cl_obj; 241 test_b34<int&>(cl); 242 test_b34<int const&>(static_cast<Fn const*>(cl)); 243 } 244 return true; 245 } 246 247 constexpr bool bullet_five_tests() { 248 using FooType = const int&(NonCopyable&&); 249 { 250 FooType& fn = foo; 251 test_b5<const int &>(fn); 252 } 253 { 254 FooType* fn = foo; 255 test_b5<const int &>(fn); 256 } 257 { 258 typedef TestClass Fn; 259 Fn cl(42); 260 test_b5<int&>(cl); 261 test_b5<int const&>(static_cast<Fn const&>(cl)); 262 263 test_b5<int&&>(static_cast<Fn &&>(cl)); 264 test_b5<int const&&>(static_cast<Fn const&&>(cl)); 265 } 266 return true; 267 } 268 269 int main(int, char**) { 270 bullet_one_two_tests(); 271 bullet_three_four_tests(); 272 bullet_five_tests(); 273 274 static_assert(bullet_one_two_tests()); 275 static_assert(bullet_three_four_tests()); 276 static_assert(bullet_five_tests()); 277 278 return 0; 279 } 280