1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___FUNCTIONAL_INVOKE_H 11 #define _LIBCPP___FUNCTIONAL_INVOKE_H 12 13 #include <__config> 14 #include <__type_traits/add_lvalue_reference.h> 15 #include <__type_traits/apply_cv.h> 16 #include <__type_traits/conditional.h> 17 #include <__type_traits/decay.h> 18 #include <__type_traits/enable_if.h> 19 #include <__type_traits/integral_constant.h> 20 #include <__type_traits/is_base_of.h> 21 #include <__type_traits/is_core_convertible.h> 22 #include <__type_traits/is_member_function_pointer.h> 23 #include <__type_traits/is_member_object_pointer.h> 24 #include <__type_traits/is_reference_wrapper.h> 25 #include <__type_traits/is_same.h> 26 #include <__type_traits/is_void.h> 27 #include <__type_traits/remove_cv.h> 28 #include <__utility/declval.h> 29 #include <__utility/forward.h> 30 31 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 32 # pragma GCC system_header 33 #endif 34 35 // TODO: Disentangle the type traits and std::invoke properly 36 37 _LIBCPP_BEGIN_NAMESPACE_STD 38 39 struct __any 40 { 41 __any(...); 42 }; 43 44 struct __nat 45 { 46 #ifndef _LIBCPP_CXX03_LANG 47 __nat() = delete; 48 __nat(const __nat&) = delete; 49 __nat& operator=(const __nat&) = delete; 50 ~__nat() = delete; 51 #endif 52 }; 53 54 template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr> 55 struct __member_pointer_traits_imp 56 { 57 }; 58 59 template <class _Rp, class _Class, class ..._Param> 60 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> 61 { 62 typedef _Class _ClassType; 63 typedef _Rp _ReturnType; 64 typedef _Rp (_FnType) (_Param...); 65 }; 66 67 template <class _Rp, class _Class, class ..._Param> 68 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> 69 { 70 typedef _Class _ClassType; 71 typedef _Rp _ReturnType; 72 typedef _Rp (_FnType) (_Param..., ...); 73 }; 74 75 template <class _Rp, class _Class, class ..._Param> 76 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> 77 { 78 typedef _Class const _ClassType; 79 typedef _Rp _ReturnType; 80 typedef _Rp (_FnType) (_Param...); 81 }; 82 83 template <class _Rp, class _Class, class ..._Param> 84 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false> 85 { 86 typedef _Class const _ClassType; 87 typedef _Rp _ReturnType; 88 typedef _Rp (_FnType) (_Param..., ...); 89 }; 90 91 template <class _Rp, class _Class, class ..._Param> 92 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> 93 { 94 typedef _Class volatile _ClassType; 95 typedef _Rp _ReturnType; 96 typedef _Rp (_FnType) (_Param...); 97 }; 98 99 template <class _Rp, class _Class, class ..._Param> 100 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> 101 { 102 typedef _Class volatile _ClassType; 103 typedef _Rp _ReturnType; 104 typedef _Rp (_FnType) (_Param..., ...); 105 }; 106 107 template <class _Rp, class _Class, class ..._Param> 108 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> 109 { 110 typedef _Class const volatile _ClassType; 111 typedef _Rp _ReturnType; 112 typedef _Rp (_FnType) (_Param...); 113 }; 114 115 template <class _Rp, class _Class, class ..._Param> 116 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> 117 { 118 typedef _Class const volatile _ClassType; 119 typedef _Rp _ReturnType; 120 typedef _Rp (_FnType) (_Param..., ...); 121 }; 122 123 template <class _Rp, class _Class, class ..._Param> 124 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &, true, false> 125 { 126 typedef _Class& _ClassType; 127 typedef _Rp _ReturnType; 128 typedef _Rp (_FnType) (_Param...); 129 }; 130 131 template <class _Rp, class _Class, class ..._Param> 132 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &, true, false> 133 { 134 typedef _Class& _ClassType; 135 typedef _Rp _ReturnType; 136 typedef _Rp (_FnType) (_Param..., ...); 137 }; 138 139 template <class _Rp, class _Class, class ..._Param> 140 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&, true, false> 141 { 142 typedef _Class const& _ClassType; 143 typedef _Rp _ReturnType; 144 typedef _Rp (_FnType) (_Param...); 145 }; 146 147 template <class _Rp, class _Class, class ..._Param> 148 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false> 149 { 150 typedef _Class const& _ClassType; 151 typedef _Rp _ReturnType; 152 typedef _Rp (_FnType) (_Param..., ...); 153 }; 154 155 template <class _Rp, class _Class, class ..._Param> 156 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> 157 { 158 typedef _Class volatile& _ClassType; 159 typedef _Rp _ReturnType; 160 typedef _Rp (_FnType) (_Param...); 161 }; 162 163 template <class _Rp, class _Class, class ..._Param> 164 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> 165 { 166 typedef _Class volatile& _ClassType; 167 typedef _Rp _ReturnType; 168 typedef _Rp (_FnType) (_Param..., ...); 169 }; 170 171 template <class _Rp, class _Class, class ..._Param> 172 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> 173 { 174 typedef _Class const volatile& _ClassType; 175 typedef _Rp _ReturnType; 176 typedef _Rp (_FnType) (_Param...); 177 }; 178 179 template <class _Rp, class _Class, class ..._Param> 180 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> 181 { 182 typedef _Class const volatile& _ClassType; 183 typedef _Rp _ReturnType; 184 typedef _Rp (_FnType) (_Param..., ...); 185 }; 186 187 template <class _Rp, class _Class, class ..._Param> 188 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) &&, true, false> 189 { 190 typedef _Class&& _ClassType; 191 typedef _Rp _ReturnType; 192 typedef _Rp (_FnType) (_Param...); 193 }; 194 195 template <class _Rp, class _Class, class ..._Param> 196 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) &&, true, false> 197 { 198 typedef _Class&& _ClassType; 199 typedef _Rp _ReturnType; 200 typedef _Rp (_FnType) (_Param..., ...); 201 }; 202 203 template <class _Rp, class _Class, class ..._Param> 204 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const&&, true, false> 205 { 206 typedef _Class const&& _ClassType; 207 typedef _Rp _ReturnType; 208 typedef _Rp (_FnType) (_Param...); 209 }; 210 211 template <class _Rp, class _Class, class ..._Param> 212 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false> 213 { 214 typedef _Class const&& _ClassType; 215 typedef _Rp _ReturnType; 216 typedef _Rp (_FnType) (_Param..., ...); 217 }; 218 219 template <class _Rp, class _Class, class ..._Param> 220 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> 221 { 222 typedef _Class volatile&& _ClassType; 223 typedef _Rp _ReturnType; 224 typedef _Rp (_FnType) (_Param...); 225 }; 226 227 template <class _Rp, class _Class, class ..._Param> 228 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> 229 { 230 typedef _Class volatile&& _ClassType; 231 typedef _Rp _ReturnType; 232 typedef _Rp (_FnType) (_Param..., ...); 233 }; 234 235 template <class _Rp, class _Class, class ..._Param> 236 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> 237 { 238 typedef _Class const volatile&& _ClassType; 239 typedef _Rp _ReturnType; 240 typedef _Rp (_FnType) (_Param...); 241 }; 242 243 template <class _Rp, class _Class, class ..._Param> 244 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> 245 { 246 typedef _Class const volatile&& _ClassType; 247 typedef _Rp _ReturnType; 248 typedef _Rp (_FnType) (_Param..., ...); 249 }; 250 251 template <class _Rp, class _Class> 252 struct __member_pointer_traits_imp<_Rp _Class::*, false, true> 253 { 254 typedef _Class _ClassType; 255 typedef _Rp _ReturnType; 256 }; 257 258 template <class _MP> 259 struct __member_pointer_traits 260 : public __member_pointer_traits_imp<typename remove_cv<_MP>::type, 261 is_member_function_pointer<_MP>::value, 262 is_member_object_pointer<_MP>::value> 263 { 264 // typedef ... _ClassType; 265 // typedef ... _ReturnType; 266 // typedef ... _FnType; 267 }; 268 269 template <class _DecayedFp> 270 struct __member_pointer_class_type {}; 271 272 template <class _Ret, class _ClassType> 273 struct __member_pointer_class_type<_Ret _ClassType::*> { 274 typedef _ClassType type; 275 }; 276 277 template <class _Fp, class _A0, 278 class _DecayFp = typename decay<_Fp>::type, 279 class _DecayA0 = typename decay<_A0>::type, 280 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 281 using __enable_if_bullet1 = typename enable_if 282 < 283 is_member_function_pointer<_DecayFp>::value 284 && is_base_of<_ClassT, _DecayA0>::value 285 >::type; 286 287 template <class _Fp, class _A0, 288 class _DecayFp = typename decay<_Fp>::type, 289 class _DecayA0 = typename decay<_A0>::type> 290 using __enable_if_bullet2 = typename enable_if 291 < 292 is_member_function_pointer<_DecayFp>::value 293 && __is_reference_wrapper<_DecayA0>::value 294 >::type; 295 296 template <class _Fp, class _A0, 297 class _DecayFp = typename decay<_Fp>::type, 298 class _DecayA0 = typename decay<_A0>::type, 299 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 300 using __enable_if_bullet3 = typename enable_if 301 < 302 is_member_function_pointer<_DecayFp>::value 303 && !is_base_of<_ClassT, _DecayA0>::value 304 && !__is_reference_wrapper<_DecayA0>::value 305 >::type; 306 307 template <class _Fp, class _A0, 308 class _DecayFp = typename decay<_Fp>::type, 309 class _DecayA0 = typename decay<_A0>::type, 310 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 311 using __enable_if_bullet4 = typename enable_if 312 < 313 is_member_object_pointer<_DecayFp>::value 314 && is_base_of<_ClassT, _DecayA0>::value 315 >::type; 316 317 template <class _Fp, class _A0, 318 class _DecayFp = typename decay<_Fp>::type, 319 class _DecayA0 = typename decay<_A0>::type> 320 using __enable_if_bullet5 = typename enable_if 321 < 322 is_member_object_pointer<_DecayFp>::value 323 && __is_reference_wrapper<_DecayA0>::value 324 >::type; 325 326 template <class _Fp, class _A0, 327 class _DecayFp = typename decay<_Fp>::type, 328 class _DecayA0 = typename decay<_A0>::type, 329 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 330 using __enable_if_bullet6 = typename enable_if 331 < 332 is_member_object_pointer<_DecayFp>::value 333 && !is_base_of<_ClassT, _DecayA0>::value 334 && !__is_reference_wrapper<_DecayA0>::value 335 >::type; 336 337 // __invoke forward declarations 338 339 // fall back - none of the bullets 340 341 template <class ..._Args> 342 __nat __invoke(__any, _Args&& ...__args); 343 344 // bullets 1, 2 and 3 345 346 template <class _Fp, class _A0, class ..._Args, 347 class = __enable_if_bullet1<_Fp, _A0> > 348 inline _LIBCPP_INLINE_VISIBILITY 349 _LIBCPP_CONSTEXPR decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...)) 350 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) 351 _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...))) 352 { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); } 353 354 template <class _Fp, class _A0, class ..._Args, 355 class = __enable_if_bullet2<_Fp, _A0> > 356 inline _LIBCPP_INLINE_VISIBILITY 357 _LIBCPP_CONSTEXPR decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...)) 358 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) 359 _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...))) 360 { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); } 361 362 template <class _Fp, class _A0, class ..._Args, 363 class = __enable_if_bullet3<_Fp, _A0> > 364 inline _LIBCPP_INLINE_VISIBILITY 365 _LIBCPP_CONSTEXPR decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...)) 366 __invoke(_Fp&& __f, _A0&& __a0, _Args&& ...__args) 367 _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...))) 368 { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); } 369 370 // bullets 4, 5 and 6 371 372 template <class _Fp, class _A0, 373 class = __enable_if_bullet4<_Fp, _A0> > 374 inline _LIBCPP_INLINE_VISIBILITY 375 _LIBCPP_CONSTEXPR decltype(std::declval<_A0>().*std::declval<_Fp>()) 376 __invoke(_Fp&& __f, _A0&& __a0) 377 _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f)) 378 { return static_cast<_A0&&>(__a0).*__f; } 379 380 template <class _Fp, class _A0, 381 class = __enable_if_bullet5<_Fp, _A0> > 382 inline _LIBCPP_INLINE_VISIBILITY 383 _LIBCPP_CONSTEXPR decltype(std::declval<_A0>().get().*std::declval<_Fp>()) 384 __invoke(_Fp&& __f, _A0&& __a0) 385 _NOEXCEPT_(noexcept(__a0.get().*__f)) 386 { return __a0.get().*__f; } 387 388 template <class _Fp, class _A0, 389 class = __enable_if_bullet6<_Fp, _A0> > 390 inline _LIBCPP_INLINE_VISIBILITY 391 _LIBCPP_CONSTEXPR decltype((*std::declval<_A0>()).*std::declval<_Fp>()) 392 __invoke(_Fp&& __f, _A0&& __a0) 393 _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f)) 394 { return (*static_cast<_A0&&>(__a0)).*__f; } 395 396 // bullet 7 397 398 template <class _Fp, class ..._Args> 399 inline _LIBCPP_INLINE_VISIBILITY 400 _LIBCPP_CONSTEXPR decltype(std::declval<_Fp>()(std::declval<_Args>()...)) 401 __invoke(_Fp&& __f, _Args&& ...__args) 402 _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...))) 403 { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); } 404 405 // __invokable 406 template <class _Ret, class _Fp, class ..._Args> 407 struct __invokable_r 408 { 409 template <class _XFp, class ..._XArgs> 410 static decltype(std::__invoke(declval<_XFp>(), declval<_XArgs>()...)) __try_call(int); 411 template <class _XFp, class ..._XArgs> 412 static __nat __try_call(...); 413 414 // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void, 415 // or incomplete array types as required by the standard. 416 using _Result = decltype(__try_call<_Fp, _Args...>(0)); 417 418 using type = typename conditional< 419 _IsNotSame<_Result, __nat>::value, 420 typename conditional< is_void<_Ret>::value, true_type, __is_core_convertible<_Result, _Ret> >::type, 421 false_type >::type; 422 static const bool value = type::value; 423 }; 424 template <class _Fp, class ..._Args> 425 using __invokable = __invokable_r<void, _Fp, _Args...>; 426 427 template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class ..._Args> 428 struct __nothrow_invokable_r_imp { 429 static const bool value = false; 430 }; 431 432 template <class _Ret, class _Fp, class ..._Args> 433 struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> 434 { 435 typedef __nothrow_invokable_r_imp _ThisT; 436 437 template <class _Tp> 438 static void __test_noexcept(_Tp) _NOEXCEPT; 439 440 static const bool value = noexcept(_ThisT::__test_noexcept<_Ret>( 441 _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...))); 442 }; 443 444 template <class _Ret, class _Fp, class ..._Args> 445 struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> 446 { 447 static const bool value = noexcept( 448 _VSTD::__invoke(declval<_Fp>(), declval<_Args>()...)); 449 }; 450 451 template <class _Ret, class _Fp, class ..._Args> 452 using __nothrow_invokable_r = 453 __nothrow_invokable_r_imp< 454 __invokable_r<_Ret, _Fp, _Args...>::value, 455 is_void<_Ret>::value, 456 _Ret, _Fp, _Args... 457 >; 458 459 template <class _Fp, class ..._Args> 460 using __nothrow_invokable = 461 __nothrow_invokable_r_imp< 462 __invokable<_Fp, _Args...>::value, 463 true, void, _Fp, _Args... 464 >; 465 466 template <class _Fp, class ..._Args> 467 struct __invoke_of 468 : public enable_if< 469 __invokable<_Fp, _Args...>::value, 470 typename __invokable_r<void, _Fp, _Args...>::_Result> 471 { 472 }; 473 474 template <class _Ret, bool = is_void<_Ret>::value> 475 struct __invoke_void_return_wrapper 476 { 477 template <class ..._Args> 478 static _Ret __call(_Args&&... __args) { 479 return std::__invoke(std::forward<_Args>(__args)...); 480 } 481 }; 482 483 template <class _Ret> 484 struct __invoke_void_return_wrapper<_Ret, true> 485 { 486 template <class ..._Args> 487 static void __call(_Args&&... __args) { 488 std::__invoke(std::forward<_Args>(__args)...); 489 } 490 }; 491 492 #if _LIBCPP_STD_VER > 14 493 494 // is_invocable 495 496 template <class _Fn, class ..._Args> 497 struct _LIBCPP_TEMPLATE_VIS is_invocable 498 : integral_constant<bool, __invokable<_Fn, _Args...>::value> {}; 499 500 template <class _Ret, class _Fn, class ..._Args> 501 struct _LIBCPP_TEMPLATE_VIS is_invocable_r 502 : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {}; 503 504 template <class _Fn, class ..._Args> 505 inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; 506 507 template <class _Ret, class _Fn, class ..._Args> 508 inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; 509 510 // is_nothrow_invocable 511 512 template <class _Fn, class ..._Args> 513 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable 514 : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> {}; 515 516 template <class _Ret, class _Fn, class ..._Args> 517 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r 518 : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {}; 519 520 template <class _Fn, class ..._Args> 521 inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value; 522 523 template <class _Ret, class _Fn, class ..._Args> 524 inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; 525 526 template <class _Fn, class... _Args> 527 struct _LIBCPP_TEMPLATE_VIS invoke_result 528 : __invoke_of<_Fn, _Args...> 529 { 530 }; 531 532 template <class _Fn, class... _Args> 533 using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; 534 535 template <class _Fn, class ..._Args> 536 _LIBCPP_CONSTEXPR_AFTER_CXX17 invoke_result_t<_Fn, _Args...> 537 invoke(_Fn&& __f, _Args&&... __args) 538 noexcept(is_nothrow_invocable_v<_Fn, _Args...>) 539 { 540 return _VSTD::__invoke(_VSTD::forward<_Fn>(__f), _VSTD::forward<_Args>(__args)...); 541 } 542 543 #endif // _LIBCPP_STD_VER > 14 544 545 _LIBCPP_END_NAMESPACE_STD 546 547 #endif // _LIBCPP___FUNCTIONAL_INVOKE_H 548