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___TYPE_TRAITS_INVOKE_H 11 #define _LIBCPP___TYPE_TRAITS_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/nat.h> 28 #include <__type_traits/remove_cv.h> 29 #include <__utility/declval.h> 30 #include <__utility/forward.h> 31 32 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 33 # pragma GCC system_header 34 #endif 35 36 _LIBCPP_BEGIN_NAMESPACE_STD 37 38 struct __any { 39 __any(...); 40 }; 41 42 template <class _MP, bool _IsMemberFunctionPtr, bool _IsMemberObjectPtr> 43 struct __member_pointer_traits_imp {}; 44 45 template <class _Rp, class _Class, class... _Param> 46 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...), true, false> { 47 typedef _Class _ClassType; 48 typedef _Rp _ReturnType; 49 typedef _Rp(_FnType)(_Param...); 50 }; 51 52 template <class _Rp, class _Class, class... _Param> 53 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), true, false> { 54 typedef _Class _ClassType; 55 typedef _Rp _ReturnType; 56 typedef _Rp(_FnType)(_Param..., ...); 57 }; 58 59 template <class _Rp, class _Class, class... _Param> 60 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const, true, false> { 61 typedef _Class const _ClassType; 62 typedef _Rp _ReturnType; 63 typedef _Rp(_FnType)(_Param...); 64 }; 65 66 template <class _Rp, class _Class, class... _Param> 67 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const, true, false> { 68 typedef _Class const _ClassType; 69 typedef _Rp _ReturnType; 70 typedef _Rp(_FnType)(_Param..., ...); 71 }; 72 73 template <class _Rp, class _Class, class... _Param> 74 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile, true, false> { 75 typedef _Class volatile _ClassType; 76 typedef _Rp _ReturnType; 77 typedef _Rp(_FnType)(_Param...); 78 }; 79 80 template <class _Rp, class _Class, class... _Param> 81 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile, true, false> { 82 typedef _Class volatile _ClassType; 83 typedef _Rp _ReturnType; 84 typedef _Rp(_FnType)(_Param..., ...); 85 }; 86 87 template <class _Rp, class _Class, class... _Param> 88 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile, true, false> { 89 typedef _Class const volatile _ClassType; 90 typedef _Rp _ReturnType; 91 typedef _Rp(_FnType)(_Param...); 92 }; 93 94 template <class _Rp, class _Class, class... _Param> 95 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile, true, false> { 96 typedef _Class const volatile _ClassType; 97 typedef _Rp _ReturnType; 98 typedef _Rp(_FnType)(_Param..., ...); 99 }; 100 101 template <class _Rp, class _Class, class... _Param> 102 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...)&, true, false> { 103 typedef _Class& _ClassType; 104 typedef _Rp _ReturnType; 105 typedef _Rp(_FnType)(_Param...); 106 }; 107 108 template <class _Rp, class _Class, class... _Param> 109 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...)&, true, false> { 110 typedef _Class& _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&, true, false> { 117 typedef _Class const& _ClassType; 118 typedef _Rp _ReturnType; 119 typedef _Rp(_FnType)(_Param...); 120 }; 121 122 template <class _Rp, class _Class, class... _Param> 123 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&, true, false> { 124 typedef _Class const& _ClassType; 125 typedef _Rp _ReturnType; 126 typedef _Rp(_FnType)(_Param..., ...); 127 }; 128 129 template <class _Rp, class _Class, class... _Param> 130 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&, true, false> { 131 typedef _Class volatile& _ClassType; 132 typedef _Rp _ReturnType; 133 typedef _Rp(_FnType)(_Param...); 134 }; 135 136 template <class _Rp, class _Class, class... _Param> 137 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&, true, false> { 138 typedef _Class volatile& _ClassType; 139 typedef _Rp _ReturnType; 140 typedef _Rp(_FnType)(_Param..., ...); 141 }; 142 143 template <class _Rp, class _Class, class... _Param> 144 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&, true, false> { 145 typedef _Class const volatile& _ClassType; 146 typedef _Rp _ReturnType; 147 typedef _Rp(_FnType)(_Param...); 148 }; 149 150 template <class _Rp, class _Class, class... _Param> 151 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&, true, false> { 152 typedef _Class const volatile& _ClassType; 153 typedef _Rp _ReturnType; 154 typedef _Rp(_FnType)(_Param..., ...); 155 }; 156 157 template <class _Rp, class _Class, class... _Param> 158 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...)&&, true, false> { 159 typedef _Class&& _ClassType; 160 typedef _Rp _ReturnType; 161 typedef _Rp(_FnType)(_Param...); 162 }; 163 164 template <class _Rp, class _Class, class... _Param> 165 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...)&&, true, false> { 166 typedef _Class&& _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&&, true, false> { 173 typedef _Class const&& _ClassType; 174 typedef _Rp _ReturnType; 175 typedef _Rp(_FnType)(_Param...); 176 }; 177 178 template <class _Rp, class _Class, class... _Param> 179 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const&&, true, false> { 180 typedef _Class const&& _ClassType; 181 typedef _Rp _ReturnType; 182 typedef _Rp(_FnType)(_Param..., ...); 183 }; 184 185 template <class _Rp, class _Class, class... _Param> 186 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) volatile&&, true, false> { 187 typedef _Class volatile&& _ClassType; 188 typedef _Rp _ReturnType; 189 typedef _Rp(_FnType)(_Param...); 190 }; 191 192 template <class _Rp, class _Class, class... _Param> 193 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) volatile&&, true, false> { 194 typedef _Class volatile&& _ClassType; 195 typedef _Rp _ReturnType; 196 typedef _Rp(_FnType)(_Param..., ...); 197 }; 198 199 template <class _Rp, class _Class, class... _Param> 200 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param...) const volatile&&, true, false> { 201 typedef _Class const volatile&& _ClassType; 202 typedef _Rp _ReturnType; 203 typedef _Rp(_FnType)(_Param...); 204 }; 205 206 template <class _Rp, class _Class, class... _Param> 207 struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...) const volatile&&, true, false> { 208 typedef _Class const volatile&& _ClassType; 209 typedef _Rp _ReturnType; 210 typedef _Rp(_FnType)(_Param..., ...); 211 }; 212 213 template <class _Rp, class _Class> 214 struct __member_pointer_traits_imp<_Rp _Class::*, false, true> { 215 typedef _Class _ClassType; 216 typedef _Rp _ReturnType; 217 }; 218 219 template <class _MP> 220 struct __member_pointer_traits 221 : public __member_pointer_traits_imp<__remove_cv_t<_MP>, 222 is_member_function_pointer<_MP>::value, 223 is_member_object_pointer<_MP>::value> { 224 // typedef ... _ClassType; 225 // typedef ... _ReturnType; 226 // typedef ... _FnType; 227 }; 228 229 template <class _DecayedFp> 230 struct __member_pointer_class_type {}; 231 232 template <class _Ret, class _ClassType> 233 struct __member_pointer_class_type<_Ret _ClassType::*> { 234 typedef _ClassType type; 235 }; 236 237 template <class _Fp, 238 class _A0, 239 class _DecayFp = __decay_t<_Fp>, 240 class _DecayA0 = __decay_t<_A0>, 241 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 242 using __enable_if_bullet1 = 243 __enable_if_t<is_member_function_pointer<_DecayFp>::value && 244 (is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value)>; 245 246 template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> > 247 using __enable_if_bullet2 = 248 __enable_if_t<is_member_function_pointer<_DecayFp>::value && __is_reference_wrapper<_DecayA0>::value>; 249 250 template <class _Fp, 251 class _A0, 252 class _DecayFp = __decay_t<_Fp>, 253 class _DecayA0 = __decay_t<_A0>, 254 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 255 using __enable_if_bullet3 = 256 __enable_if_t<is_member_function_pointer<_DecayFp>::value && 257 !(is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value) && 258 !__is_reference_wrapper<_DecayA0>::value>; 259 260 template <class _Fp, 261 class _A0, 262 class _DecayFp = __decay_t<_Fp>, 263 class _DecayA0 = __decay_t<_A0>, 264 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 265 using __enable_if_bullet4 = 266 __enable_if_t<is_member_object_pointer<_DecayFp>::value && 267 (is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value)>; 268 269 template <class _Fp, class _A0, class _DecayFp = __decay_t<_Fp>, class _DecayA0 = __decay_t<_A0> > 270 using __enable_if_bullet5 = 271 __enable_if_t<is_member_object_pointer<_DecayFp>::value && __is_reference_wrapper<_DecayA0>::value>; 272 273 template <class _Fp, 274 class _A0, 275 class _DecayFp = __decay_t<_Fp>, 276 class _DecayA0 = __decay_t<_A0>, 277 class _ClassT = typename __member_pointer_class_type<_DecayFp>::type> 278 using __enable_if_bullet6 = 279 __enable_if_t<is_member_object_pointer<_DecayFp>::value && 280 !(is_same<_ClassT, _DecayA0>::value || is_base_of<_ClassT, _DecayA0>::value) && 281 !__is_reference_wrapper<_DecayA0>::value>; 282 283 // __invoke forward declarations 284 285 // fall back - none of the bullets 286 287 template <class... _Args> 288 __nat __invoke(__any, _Args&&... __args); 289 290 // bullets 1, 2 and 3 291 292 // clang-format off 293 template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet1<_Fp, _A0> > 294 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 295 decltype((std::declval<_A0>().*std::declval<_Fp>())(std::declval<_Args>()...)) 296 __invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args) 297 _NOEXCEPT_(noexcept((static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...))) 298 { return (static_cast<_A0&&>(__a0).*__f)(static_cast<_Args&&>(__args)...); } 299 300 template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet2<_Fp, _A0> > 301 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 302 decltype((std::declval<_A0>().get().*std::declval<_Fp>())(std::declval<_Args>()...)) 303 __invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args) 304 _NOEXCEPT_(noexcept((__a0.get().*__f)(static_cast<_Args&&>(__args)...))) 305 { return (__a0.get().*__f)(static_cast<_Args&&>(__args)...); } 306 307 template <class _Fp, class _A0, class... _Args, class = __enable_if_bullet3<_Fp, _A0> > 308 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 309 decltype(((*std::declval<_A0>()).*std::declval<_Fp>())(std::declval<_Args>()...)) 310 __invoke(_Fp&& __f, _A0&& __a0, _Args&&... __args) 311 _NOEXCEPT_(noexcept(((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...))) 312 { return ((*static_cast<_A0&&>(__a0)).*__f)(static_cast<_Args&&>(__args)...); } 313 314 // bullets 4, 5 and 6 315 316 template <class _Fp, class _A0, class = __enable_if_bullet4<_Fp, _A0> > 317 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 318 decltype(std::declval<_A0>().*std::declval<_Fp>()) 319 __invoke(_Fp&& __f, _A0&& __a0) 320 _NOEXCEPT_(noexcept(static_cast<_A0&&>(__a0).*__f)) 321 { return static_cast<_A0&&>(__a0).*__f; } 322 323 template <class _Fp, class _A0, class = __enable_if_bullet5<_Fp, _A0> > 324 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 325 decltype(std::declval<_A0>().get().*std::declval<_Fp>()) 326 __invoke(_Fp&& __f, _A0&& __a0) 327 _NOEXCEPT_(noexcept(__a0.get().*__f)) 328 { return __a0.get().*__f; } 329 330 template <class _Fp, class _A0, class = __enable_if_bullet6<_Fp, _A0> > 331 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 332 decltype((*std::declval<_A0>()).*std::declval<_Fp>()) 333 __invoke(_Fp&& __f, _A0&& __a0) 334 _NOEXCEPT_(noexcept((*static_cast<_A0&&>(__a0)).*__f)) 335 { return (*static_cast<_A0&&>(__a0)).*__f; } 336 337 // bullet 7 338 339 template <class _Fp, class... _Args> 340 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR 341 decltype(std::declval<_Fp>()(std::declval<_Args>()...)) 342 __invoke(_Fp&& __f, _Args&&... __args) 343 _NOEXCEPT_(noexcept(static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...))) 344 { return static_cast<_Fp&&>(__f)(static_cast<_Args&&>(__args)...); } 345 // clang-format on 346 347 // __invokable 348 template <class _Ret, class _Fp, class... _Args> 349 struct __invokable_r { 350 template <class _XFp, class... _XArgs> 351 static decltype(std::__invoke(std::declval<_XFp>(), std::declval<_XArgs>()...)) __try_call(int); 352 template <class _XFp, class... _XArgs> 353 static __nat __try_call(...); 354 355 // FIXME: Check that _Ret, _Fp, and _Args... are all complete types, cv void, 356 // or incomplete array types as required by the standard. 357 using _Result = decltype(__try_call<_Fp, _Args...>(0)); 358 359 using type = __conditional_t<_IsNotSame<_Result, __nat>::value, 360 __conditional_t<is_void<_Ret>::value, true_type, __is_core_convertible<_Result, _Ret> >, 361 false_type>; 362 static const bool value = type::value; 363 }; 364 template <class _Fp, class... _Args> 365 using __invokable = __invokable_r<void, _Fp, _Args...>; 366 367 template <bool _IsInvokable, bool _IsCVVoid, class _Ret, class _Fp, class... _Args> 368 struct __nothrow_invokable_r_imp { 369 static const bool value = false; 370 }; 371 372 template <class _Ret, class _Fp, class... _Args> 373 struct __nothrow_invokable_r_imp<true, false, _Ret, _Fp, _Args...> { 374 typedef __nothrow_invokable_r_imp _ThisT; 375 376 template <class _Tp> 377 static void __test_noexcept(_Tp) _NOEXCEPT; 378 379 #ifdef _LIBCPP_CXX03_LANG 380 static const bool value = false; 381 #else 382 static const bool value = 383 noexcept(_ThisT::__test_noexcept<_Ret>(std::__invoke(std::declval<_Fp>(), std::declval<_Args>()...))); 384 #endif 385 }; 386 387 template <class _Ret, class _Fp, class... _Args> 388 struct __nothrow_invokable_r_imp<true, true, _Ret, _Fp, _Args...> { 389 #ifdef _LIBCPP_CXX03_LANG 390 static const bool value = false; 391 #else 392 static const bool value = noexcept(std::__invoke(std::declval<_Fp>(), std::declval<_Args>()...)); 393 #endif 394 }; 395 396 template <class _Ret, class _Fp, class... _Args> 397 using __nothrow_invokable_r = 398 __nothrow_invokable_r_imp<__invokable_r<_Ret, _Fp, _Args...>::value, is_void<_Ret>::value, _Ret, _Fp, _Args...>; 399 400 template <class _Fp, class... _Args> 401 using __nothrow_invokable = __nothrow_invokable_r_imp<__invokable<_Fp, _Args...>::value, true, void, _Fp, _Args...>; 402 403 template <class _Fp, class... _Args> 404 struct __invoke_of 405 : public enable_if<__invokable<_Fp, _Args...>::value, typename __invokable_r<void, _Fp, _Args...>::_Result> {}; 406 407 template <class _Ret, bool = is_void<_Ret>::value> 408 struct __invoke_void_return_wrapper { 409 template <class... _Args> 410 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static _Ret __call(_Args&&... __args) { 411 return std::__invoke(std::forward<_Args>(__args)...); 412 } 413 }; 414 415 template <class _Ret> 416 struct __invoke_void_return_wrapper<_Ret, true> { 417 template <class... _Args> 418 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void __call(_Args&&... __args) { 419 std::__invoke(std::forward<_Args>(__args)...); 420 } 421 }; 422 423 #if _LIBCPP_STD_VER >= 17 424 425 // is_invocable 426 427 template <class _Fn, class... _Args> 428 struct _LIBCPP_TEMPLATE_VIS is_invocable : integral_constant<bool, __invokable<_Fn, _Args...>::value> {}; 429 430 template <class _Ret, class _Fn, class... _Args> 431 struct _LIBCPP_TEMPLATE_VIS is_invocable_r : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {}; 432 433 template <class _Fn, class... _Args> 434 inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; 435 436 template <class _Ret, class _Fn, class... _Args> 437 inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; 438 439 // is_nothrow_invocable 440 441 template <class _Fn, class... _Args> 442 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable : integral_constant<bool, __nothrow_invokable<_Fn, _Args...>::value> { 443 }; 444 445 template <class _Ret, class _Fn, class... _Args> 446 struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r 447 : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {}; 448 449 template <class _Fn, class... _Args> 450 inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value; 451 452 template <class _Ret, class _Fn, class... _Args> 453 inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; 454 455 template <class _Fn, class... _Args> 456 struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_of<_Fn, _Args...> {}; 457 458 template <class _Fn, class... _Args> 459 using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; 460 461 #endif // _LIBCPP_STD_VER >= 17 462 463 _LIBCPP_END_NAMESPACE_STD 464 465 #endif // _LIBCPP___TYPE_TRAITS_INVOKE_H 466