1 // Copyright 2022 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // Implementation details for `absl::AnyInvocable` 16 17 #ifndef ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_ 18 #define ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_ 19 20 //////////////////////////////////////////////////////////////////////////////// 21 // // 22 // This implementation chooses between local storage and remote storage for // 23 // the contained target object based on the target object's size, alignment // 24 // requirements, and whether or not it has a nothrow move constructor. // 25 // Additional optimizations are performed when the object is a trivially // 26 // copyable type [basic.types]. // 27 // // 28 // There are three datamembers per `AnyInvocable` instance // 29 // // 30 // 1) A union containing either // 31 // - A pointer to the target object referred to via a void*, or // 32 // - the target object, emplaced into a raw char buffer // 33 // // 34 // 2) A function pointer to a "manager" function operation that takes a // 35 // discriminator and logically branches to either perform a move operation // 36 // or destroy operation based on that discriminator. // 37 // // 38 // 3) A function pointer to an "invoker" function operation that invokes the // 39 // target object, directly returning the result. // 40 // // 41 // When in the logically empty state, the manager function is an empty // 42 // function and the invoker function is one that would be undefined behavior // 43 // to call. // 44 // // 45 // An additional optimization is performed when converting from one // 46 // AnyInvocable to another where only the noexcept specification and/or the // 47 // cv/ref qualifiers of the function type differ. In these cases, the // 48 // conversion works by "moving the guts", similar to if they were the same // 49 // exact type, as opposed to having to perform an additional layer of // 50 // wrapping through remote storage. // 51 // // 52 //////////////////////////////////////////////////////////////////////////////// 53 54 // IWYU pragma: private, include "absl/functional/any_invocable.h" 55 56 #include <cassert> 57 #include <cstddef> 58 #include <cstring> 59 #include <exception> 60 #include <functional> 61 #include <memory> 62 #include <new> 63 #include <type_traits> 64 #include <utility> 65 66 #include "absl/base/attributes.h" 67 #include "absl/base/config.h" 68 #include "absl/base/internal/invoke.h" 69 #include "absl/base/macros.h" 70 #include "absl/base/optimization.h" 71 #include "absl/meta/type_traits.h" 72 #include "absl/utility/utility.h" 73 74 namespace absl { 75 ABSL_NAMESPACE_BEGIN 76 77 // Helper macro used to prevent spelling `noexcept` in language versions older 78 // than C++17, where it is not part of the type system, in order to avoid 79 // compilation failures and internal compiler errors. 80 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L 81 #define ABSL_INTERNAL_NOEXCEPT_SPEC(noex) noexcept(noex) 82 #else 83 #define ABSL_INTERNAL_NOEXCEPT_SPEC(noex) 84 #endif 85 86 // Defined in functional/any_invocable.h 87 template <class Sig> 88 class AnyInvocable; 89 90 namespace internal_any_invocable { 91 92 // Constants relating to the small-object-storage for AnyInvocable 93 enum StorageProperty : std::size_t { 94 kAlignment = alignof(std::max_align_t), // The alignment of the storage 95 kStorageSize = sizeof(void*) * 2 // The size of the storage 96 }; 97 98 //////////////////////////////////////////////////////////////////////////////// 99 // 100 // A metafunction for checking if a type is an AnyInvocable instantiation. 101 // This is used during conversion operations. 102 template <class T> 103 struct IsAnyInvocable : std::false_type {}; 104 105 template <class Sig> 106 struct IsAnyInvocable<AnyInvocable<Sig>> : std::true_type {}; 107 // 108 //////////////////////////////////////////////////////////////////////////////// 109 110 // A type trait that tells us whether or not a target function type should be 111 // stored locally in the small object optimization storage 112 template <class T> 113 using IsStoredLocally = std::integral_constant< 114 bool, sizeof(T) <= kStorageSize && alignof(T) <= kAlignment && 115 kAlignment % alignof(T) == 0 && 116 std::is_nothrow_move_constructible<T>::value>; 117 118 // An implementation of std::remove_cvref_t of C++20. 119 template <class T> 120 using RemoveCVRef = 121 typename std::remove_cv<typename std::remove_reference<T>::type>::type; 122 123 //////////////////////////////////////////////////////////////////////////////// 124 // 125 // An implementation of the C++ standard INVOKE<R> pseudo-macro, operation is 126 // equivalent to std::invoke except that it forces an implicit conversion to the 127 // specified return type. If "R" is void, the function is executed and the 128 // return value is simply ignored. 129 template <class ReturnType, class F, class... P, 130 typename = absl::enable_if_t<std::is_void<ReturnType>::value>> 131 void InvokeR(F&& f, P&&... args) { 132 absl::base_internal::invoke(std::forward<F>(f), std::forward<P>(args)...); 133 } 134 135 template <class ReturnType, class F, class... P, 136 absl::enable_if_t<!std::is_void<ReturnType>::value, int> = 0> 137 ReturnType InvokeR(F&& f, P&&... args) { 138 // GCC 12 has a false-positive -Wmaybe-uninitialized warning here. 139 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0) 140 #pragma GCC diagnostic push 141 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 142 #endif 143 return absl::base_internal::invoke(std::forward<F>(f), 144 std::forward<P>(args)...); 145 #if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0) 146 #pragma GCC diagnostic pop 147 #endif 148 } 149 150 // 151 //////////////////////////////////////////////////////////////////////////////// 152 153 //////////////////////////////////////////////////////////////////////////////// 154 /// 155 // A metafunction that takes a "T" corresponding to a parameter type of the 156 // user's specified function type, and yields the parameter type to use for the 157 // type-erased invoker. In order to prevent observable moves, this must be 158 // either a reference or, if the type is trivial, the original parameter type 159 // itself. Since the parameter type may be incomplete at the point that this 160 // metafunction is used, we can only do this optimization for scalar types 161 // rather than for any trivial type. 162 template <typename T> 163 T ForwardImpl(std::true_type); 164 165 template <typename T> 166 T&& ForwardImpl(std::false_type); 167 168 // NOTE: We deliberately use an intermediate struct instead of a direct alias, 169 // as a workaround for b/206991861 on MSVC versions < 1924. 170 template <class T> 171 struct ForwardedParameter { 172 using type = decltype(( 173 ForwardImpl<T>)(std::integral_constant<bool, 174 std::is_scalar<T>::value>())); 175 }; 176 177 template <class T> 178 using ForwardedParameterType = typename ForwardedParameter<T>::type; 179 // 180 //////////////////////////////////////////////////////////////////////////////// 181 182 // A discriminator when calling the "manager" function that describes operation 183 // type-erased operation should be invoked. 184 // 185 // "relocate_from_to" specifies that the manager should perform a move. 186 // 187 // "dispose" specifies that the manager should perform a destroy. 188 enum class FunctionToCall : bool { relocate_from_to, dispose }; 189 190 // The portion of `AnyInvocable` state that contains either a pointer to the 191 // target object or the object itself in local storage 192 union TypeErasedState { 193 struct { 194 // A pointer to the type-erased object when remotely stored 195 void* target; 196 // The size of the object for `RemoteManagerTrivial` 197 std::size_t size; 198 } remote; 199 200 // Local-storage for the type-erased object when small and trivial enough 201 alignas(kAlignment) char storage[kStorageSize]; 202 }; 203 204 // A typed accessor for the object in `TypeErasedState` storage 205 template <class T> 206 T& ObjectInLocalStorage(TypeErasedState* const state) { 207 // We launder here because the storage may be reused with the same type. 208 #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L 209 return *std::launder(reinterpret_cast<T*>(&state->storage)); 210 #elif ABSL_HAVE_BUILTIN(__builtin_launder) 211 return *__builtin_launder(reinterpret_cast<T*>(&state->storage)); 212 #else 213 214 // When `std::launder` or equivalent are not available, we rely on undefined 215 // behavior, which works as intended on Abseil's officially supported 216 // platforms as of Q2 2022. 217 #if !defined(__clang__) && defined(__GNUC__) 218 #pragma GCC diagnostic push 219 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 220 #endif 221 return *reinterpret_cast<T*>(&state->storage); 222 #if !defined(__clang__) && defined(__GNUC__) 223 #pragma GCC diagnostic pop 224 #endif 225 226 #endif 227 } 228 229 // The type for functions issuing lifetime-related operations: move and dispose 230 // A pointer to such a function is contained in each `AnyInvocable` instance. 231 // NOTE: When specifying `FunctionToCall::`dispose, the same state must be 232 // passed as both "from" and "to". 233 using ManagerType = void(FunctionToCall /*operation*/, 234 TypeErasedState* /*from*/, TypeErasedState* /*to*/) 235 ABSL_INTERNAL_NOEXCEPT_SPEC(true); 236 237 // The type for functions issuing the actual invocation of the object 238 // A pointer to such a function is contained in each AnyInvocable instance. 239 template <bool SigIsNoexcept, class ReturnType, class... P> 240 using InvokerType = ReturnType(TypeErasedState*, ForwardedParameterType<P>...) 241 ABSL_INTERNAL_NOEXCEPT_SPEC(SigIsNoexcept); 242 243 // The manager that is used when AnyInvocable is empty 244 inline void EmptyManager(FunctionToCall /*operation*/, 245 TypeErasedState* /*from*/, 246 TypeErasedState* /*to*/) noexcept {} 247 248 // The manager that is used when a target function is in local storage and is 249 // a trivially copyable type. 250 inline void LocalManagerTrivial(FunctionToCall /*operation*/, 251 TypeErasedState* const from, 252 TypeErasedState* const to) noexcept { 253 // This single statement without branching handles both possible operations. 254 // 255 // For FunctionToCall::dispose, "from" and "to" point to the same state, and 256 // so this assignment logically would do nothing. 257 // 258 // Note: Correctness here relies on http://wg21.link/p0593, which has only 259 // become standard in C++20, though implementations do not break it in 260 // practice for earlier versions of C++. 261 // 262 // The correct way to do this without that paper is to first placement-new a 263 // default-constructed T in "to->storage" prior to the memmove, but doing so 264 // requires a different function to be created for each T that is stored 265 // locally, which can cause unnecessary bloat and be less cache friendly. 266 *to = *from; 267 268 // Note: Because the type is trivially copyable, the destructor does not need 269 // to be called ("trivially copyable" requires a trivial destructor). 270 } 271 272 // The manager that is used when a target function is in local storage and is 273 // not a trivially copyable type. 274 template <class T> 275 void LocalManagerNontrivial(FunctionToCall operation, 276 TypeErasedState* const from, 277 TypeErasedState* const to) noexcept { 278 static_assert(IsStoredLocally<T>::value, 279 "Local storage must only be used for supported types."); 280 static_assert(!std::is_trivially_copyable<T>::value, 281 "Locally stored types must be trivially copyable."); 282 283 T& from_object = (ObjectInLocalStorage<T>)(from); 284 285 switch (operation) { 286 case FunctionToCall::relocate_from_to: 287 // NOTE: Requires that the left-hand operand is already empty. 288 ::new (static_cast<void*>(&to->storage)) T(std::move(from_object)); 289 ABSL_FALLTHROUGH_INTENDED; 290 case FunctionToCall::dispose: 291 from_object.~T(); // Must not throw. // NOLINT 292 return; 293 } 294 ABSL_UNREACHABLE(); 295 } 296 297 // The invoker that is used when a target function is in local storage 298 // Note: QualTRef here is the target function type along with cv and reference 299 // qualifiers that must be used when calling the function. 300 template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P> 301 ReturnType LocalInvoker( 302 TypeErasedState* const state, 303 ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) { 304 using RawT = RemoveCVRef<QualTRef>; 305 static_assert( 306 IsStoredLocally<RawT>::value, 307 "Target object must be in local storage in order to be invoked from it."); 308 309 auto& f = (ObjectInLocalStorage<RawT>)(state); 310 return (InvokeR<ReturnType>)(static_cast<QualTRef>(f), 311 static_cast<ForwardedParameterType<P>>(args)...); 312 } 313 314 // The manager that is used when a target function is in remote storage and it 315 // has a trivial destructor 316 inline void RemoteManagerTrivial(FunctionToCall operation, 317 TypeErasedState* const from, 318 TypeErasedState* const to) noexcept { 319 switch (operation) { 320 case FunctionToCall::relocate_from_to: 321 // NOTE: Requires that the left-hand operand is already empty. 322 to->remote = from->remote; 323 return; 324 case FunctionToCall::dispose: 325 #if defined(__cpp_sized_deallocation) 326 ::operator delete(from->remote.target, from->remote.size); 327 #else // __cpp_sized_deallocation 328 ::operator delete(from->remote.target); 329 #endif // __cpp_sized_deallocation 330 return; 331 } 332 ABSL_UNREACHABLE(); 333 } 334 335 // The manager that is used when a target function is in remote storage and the 336 // destructor of the type is not trivial 337 template <class T> 338 void RemoteManagerNontrivial(FunctionToCall operation, 339 TypeErasedState* const from, 340 TypeErasedState* const to) noexcept { 341 static_assert(!IsStoredLocally<T>::value, 342 "Remote storage must only be used for types that do not " 343 "qualify for local storage."); 344 345 switch (operation) { 346 case FunctionToCall::relocate_from_to: 347 // NOTE: Requires that the left-hand operand is already empty. 348 to->remote.target = from->remote.target; 349 return; 350 case FunctionToCall::dispose: 351 ::delete static_cast<T*>(from->remote.target); // Must not throw. 352 return; 353 } 354 ABSL_UNREACHABLE(); 355 } 356 357 // The invoker that is used when a target function is in remote storage 358 template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P> 359 ReturnType RemoteInvoker( 360 TypeErasedState* const state, 361 ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) { 362 using RawT = RemoveCVRef<QualTRef>; 363 static_assert(!IsStoredLocally<RawT>::value, 364 "Target object must be in remote storage in order to be " 365 "invoked from it."); 366 367 auto& f = *static_cast<RawT*>(state->remote.target); 368 return (InvokeR<ReturnType>)(static_cast<QualTRef>(f), 369 static_cast<ForwardedParameterType<P>>(args)...); 370 } 371 372 //////////////////////////////////////////////////////////////////////////////// 373 // 374 // A metafunction that checks if a type T is an instantiation of 375 // absl::in_place_type_t (needed for constructor constraints of AnyInvocable). 376 template <class T> 377 struct IsInPlaceType : std::false_type {}; 378 379 template <class T> 380 struct IsInPlaceType<absl::in_place_type_t<T>> : std::true_type {}; 381 // 382 //////////////////////////////////////////////////////////////////////////////// 383 384 // A constructor name-tag used with CoreImpl (below) to request the 385 // conversion-constructor. QualDecayedTRef is the decayed-type of the object to 386 // wrap, along with the cv and reference qualifiers that must be applied when 387 // performing an invocation of the wrapped object. 388 template <class QualDecayedTRef> 389 struct TypedConversionConstruct {}; 390 391 // A helper base class for all core operations of AnyInvocable. Most notably, 392 // this class creates the function call operator and constraint-checkers so that 393 // the top-level class does not have to be a series of partial specializations. 394 // 395 // Note: This definition exists (as opposed to being a declaration) so that if 396 // the user of the top-level template accidentally passes a template argument 397 // that is not a function type, they will get a static_assert in AnyInvocable's 398 // class body rather than an error stating that Impl is not defined. 399 template <class Sig> 400 class Impl {}; // Note: This is partially-specialized later. 401 402 // A std::unique_ptr deleter that deletes memory allocated via ::operator new. 403 #if defined(__cpp_sized_deallocation) 404 class TrivialDeleter { 405 public: 406 explicit TrivialDeleter(std::size_t size) : size_(size) {} 407 408 void operator()(void* target) const { 409 ::operator delete(target, size_); 410 } 411 412 private: 413 std::size_t size_; 414 }; 415 #else // __cpp_sized_deallocation 416 class TrivialDeleter { 417 public: 418 explicit TrivialDeleter(std::size_t) {} 419 420 void operator()(void* target) const { ::operator delete(target); } 421 }; 422 #endif // __cpp_sized_deallocation 423 424 template <bool SigIsNoexcept, class ReturnType, class... P> 425 class CoreImpl; 426 427 constexpr bool IsCompatibleConversion(void*, void*) { return false; } 428 template <bool NoExceptSrc, bool NoExceptDest, class... T> 429 constexpr bool IsCompatibleConversion(CoreImpl<NoExceptSrc, T...>*, 430 CoreImpl<NoExceptDest, T...>*) { 431 return !NoExceptDest || NoExceptSrc; 432 } 433 434 // A helper base class for all core operations of AnyInvocable that do not 435 // depend on the cv/ref qualifiers of the function type. 436 template <bool SigIsNoexcept, class ReturnType, class... P> 437 class CoreImpl { 438 public: 439 using result_type = ReturnType; 440 441 CoreImpl() noexcept : manager_(EmptyManager), invoker_(nullptr) {} 442 443 enum class TargetType { 444 kPointer, 445 kCompatibleAnyInvocable, 446 kIncompatibleAnyInvocable, 447 kOther, 448 }; 449 450 // Note: QualDecayedTRef here includes the cv-ref qualifiers associated with 451 // the invocation of the Invocable. The unqualified type is the target object 452 // type to be stored. 453 template <class QualDecayedTRef, class F> 454 explicit CoreImpl(TypedConversionConstruct<QualDecayedTRef>, F&& f) { 455 using DecayedT = RemoveCVRef<QualDecayedTRef>; 456 457 constexpr TargetType kTargetType = 458 (std::is_pointer<DecayedT>::value || 459 std::is_member_pointer<DecayedT>::value) 460 ? TargetType::kPointer 461 : IsCompatibleAnyInvocable<DecayedT>::value 462 ? TargetType::kCompatibleAnyInvocable 463 : IsAnyInvocable<DecayedT>::value 464 ? TargetType::kIncompatibleAnyInvocable 465 : TargetType::kOther; 466 // NOTE: We only use integers instead of enums as template parameters in 467 // order to work around a bug on C++14 under MSVC 2017. 468 // See b/236131881. 469 Initialize<kTargetType, QualDecayedTRef>(std::forward<F>(f)); 470 } 471 472 // Note: QualTRef here includes the cv-ref qualifiers associated with the 473 // invocation of the Invocable. The unqualified type is the target object 474 // type to be stored. 475 template <class QualTRef, class... Args> 476 explicit CoreImpl(absl::in_place_type_t<QualTRef>, Args&&... args) { 477 InitializeStorage<QualTRef>(std::forward<Args>(args)...); 478 } 479 480 CoreImpl(CoreImpl&& other) noexcept { 481 other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_); 482 manager_ = other.manager_; 483 invoker_ = other.invoker_; 484 other.manager_ = EmptyManager; 485 other.invoker_ = nullptr; 486 } 487 488 CoreImpl& operator=(CoreImpl&& other) noexcept { 489 // Put the left-hand operand in an empty state. 490 // 491 // Note: A full reset that leaves us with an object that has its invariants 492 // intact is necessary in order to handle self-move. This is required by 493 // types that are used with certain operations of the standard library, such 494 // as the default definition of std::swap when both operands target the same 495 // object. 496 Clear(); 497 498 // Perform the actual move/destroy operation on the target function. 499 other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_); 500 manager_ = other.manager_; 501 invoker_ = other.invoker_; 502 other.manager_ = EmptyManager; 503 other.invoker_ = nullptr; 504 505 return *this; 506 } 507 508 ~CoreImpl() { manager_(FunctionToCall::dispose, &state_, &state_); } 509 510 // Check whether or not the AnyInvocable is in the empty state. 511 bool HasValue() const { return invoker_ != nullptr; } 512 513 // Effects: Puts the object into its empty state. 514 void Clear() { 515 manager_(FunctionToCall::dispose, &state_, &state_); 516 manager_ = EmptyManager; 517 invoker_ = nullptr; 518 } 519 520 template <TargetType target_type, class QualDecayedTRef, class F, 521 absl::enable_if_t<target_type == TargetType::kPointer, int> = 0> 522 void Initialize(F&& f) { 523 // This condition handles types that decay into pointers, which includes 524 // function references. Since function references cannot be null, GCC warns 525 // against comparing their decayed form with nullptr. 526 // Since this is template-heavy code, we prefer to disable these warnings 527 // locally instead of adding yet another overload of this function. 528 #if !defined(__clang__) && defined(__GNUC__) 529 #pragma GCC diagnostic push 530 #pragma GCC diagnostic ignored "-Wpragmas" 531 #pragma GCC diagnostic ignored "-Waddress" 532 #pragma GCC diagnostic ignored "-Wnonnull-compare" 533 #endif 534 if (static_cast<RemoveCVRef<QualDecayedTRef>>(f) == nullptr) { 535 #if !defined(__clang__) && defined(__GNUC__) 536 #pragma GCC diagnostic pop 537 #endif 538 manager_ = EmptyManager; 539 invoker_ = nullptr; 540 return; 541 } 542 InitializeStorage<QualDecayedTRef>(std::forward<F>(f)); 543 } 544 545 template <TargetType target_type, class QualDecayedTRef, class F, 546 absl::enable_if_t< 547 target_type == TargetType::kCompatibleAnyInvocable, int> = 0> 548 void Initialize(F&& f) { 549 // In this case we can "steal the guts" of the other AnyInvocable. 550 f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_); 551 manager_ = f.manager_; 552 invoker_ = f.invoker_; 553 554 f.manager_ = EmptyManager; 555 f.invoker_ = nullptr; 556 } 557 558 template <TargetType target_type, class QualDecayedTRef, class F, 559 absl::enable_if_t< 560 target_type == TargetType::kIncompatibleAnyInvocable, int> = 0> 561 void Initialize(F&& f) { 562 if (f.HasValue()) { 563 InitializeStorage<QualDecayedTRef>(std::forward<F>(f)); 564 } else { 565 manager_ = EmptyManager; 566 invoker_ = nullptr; 567 } 568 } 569 570 template <TargetType target_type, class QualDecayedTRef, class F, 571 typename = absl::enable_if_t<target_type == TargetType::kOther>> 572 void Initialize(F&& f) { 573 InitializeStorage<QualDecayedTRef>(std::forward<F>(f)); 574 } 575 576 // Use local (inline) storage for applicable target object types. 577 template <class QualTRef, class... Args, 578 typename = absl::enable_if_t< 579 IsStoredLocally<RemoveCVRef<QualTRef>>::value>> 580 void InitializeStorage(Args&&... args) { 581 using RawT = RemoveCVRef<QualTRef>; 582 ::new (static_cast<void*>(&state_.storage)) 583 RawT(std::forward<Args>(args)...); 584 585 invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>; 586 // We can simplify our manager if we know the type is trivially copyable. 587 InitializeLocalManager<RawT>(); 588 } 589 590 // Use remote storage for target objects that cannot be stored locally. 591 template <class QualTRef, class... Args, 592 absl::enable_if_t<!IsStoredLocally<RemoveCVRef<QualTRef>>::value, 593 int> = 0> 594 void InitializeStorage(Args&&... args) { 595 InitializeRemoteManager<RemoveCVRef<QualTRef>>(std::forward<Args>(args)...); 596 // This is set after everything else in case an exception is thrown in an 597 // earlier step of the initialization. 598 invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>; 599 } 600 601 template <class T, 602 typename = absl::enable_if_t<std::is_trivially_copyable<T>::value>> 603 void InitializeLocalManager() { 604 manager_ = LocalManagerTrivial; 605 } 606 607 template <class T, 608 absl::enable_if_t<!std::is_trivially_copyable<T>::value, int> = 0> 609 void InitializeLocalManager() { 610 manager_ = LocalManagerNontrivial<T>; 611 } 612 613 template <class T> 614 using HasTrivialRemoteStorage = 615 std::integral_constant<bool, std::is_trivially_destructible<T>::value && 616 alignof(T) <= 617 ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT>; 618 619 template <class T, class... Args, 620 typename = absl::enable_if_t<HasTrivialRemoteStorage<T>::value>> 621 void InitializeRemoteManager(Args&&... args) { 622 // unique_ptr is used for exception-safety in case construction throws. 623 std::unique_ptr<void, TrivialDeleter> uninitialized_target( 624 ::operator new(sizeof(T)), TrivialDeleter(sizeof(T))); 625 ::new (uninitialized_target.get()) T(std::forward<Args>(args)...); 626 state_.remote.target = uninitialized_target.release(); 627 state_.remote.size = sizeof(T); 628 manager_ = RemoteManagerTrivial; 629 } 630 631 template <class T, class... Args, 632 absl::enable_if_t<!HasTrivialRemoteStorage<T>::value, int> = 0> 633 void InitializeRemoteManager(Args&&... args) { 634 state_.remote.target = ::new T(std::forward<Args>(args)...); 635 manager_ = RemoteManagerNontrivial<T>; 636 } 637 638 ////////////////////////////////////////////////////////////////////////////// 639 // 640 // Type trait to determine if the template argument is an AnyInvocable whose 641 // function type is compatible enough with ours such that we can 642 // "move the guts" out of it when moving, rather than having to place a new 643 // object into remote storage. 644 645 template <typename Other> 646 struct IsCompatibleAnyInvocable { 647 static constexpr bool value = false; 648 }; 649 650 template <typename Sig> 651 struct IsCompatibleAnyInvocable<AnyInvocable<Sig>> { 652 static constexpr bool value = 653 (IsCompatibleConversion)(static_cast< 654 typename AnyInvocable<Sig>::CoreImpl*>( 655 nullptr), 656 static_cast<CoreImpl*>(nullptr)); 657 }; 658 659 // 660 ////////////////////////////////////////////////////////////////////////////// 661 662 TypeErasedState state_; 663 ManagerType* manager_; 664 InvokerType<SigIsNoexcept, ReturnType, P...>* invoker_; 665 }; 666 667 // A constructor name-tag used with Impl to request the 668 // conversion-constructor 669 struct ConversionConstruct {}; 670 671 //////////////////////////////////////////////////////////////////////////////// 672 // 673 // A metafunction that is normally an identity metafunction except that when 674 // given a std::reference_wrapper<T>, it yields T&. This is necessary because 675 // currently std::reference_wrapper's operator() is not conditionally noexcept, 676 // so when checking if such an Invocable is nothrow-invocable, we must pull out 677 // the underlying type. 678 template <class T> 679 struct UnwrapStdReferenceWrapperImpl { 680 using type = T; 681 }; 682 683 template <class T> 684 struct UnwrapStdReferenceWrapperImpl<std::reference_wrapper<T>> { 685 using type = T&; 686 }; 687 688 template <class T> 689 using UnwrapStdReferenceWrapper = 690 typename UnwrapStdReferenceWrapperImpl<T>::type; 691 // 692 //////////////////////////////////////////////////////////////////////////////// 693 694 // An alias that always yields std::true_type (used with constraints) where 695 // substitution failures happen when forming the template arguments. 696 template <class... T> 697 using TrueAlias = 698 std::integral_constant<bool, sizeof(absl::void_t<T...>*) != 0>; 699 700 /*SFINAE constraints for the conversion-constructor.*/ 701 template <class Sig, class F, 702 class = absl::enable_if_t< 703 !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>> 704 using CanConvert = TrueAlias< 705 absl::enable_if_t<!IsInPlaceType<RemoveCVRef<F>>::value>, 706 absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>, 707 absl::enable_if_t< 708 Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>, 709 absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>; 710 711 /*SFINAE constraints for the std::in_place constructors.*/ 712 template <class Sig, class F, class... Args> 713 using CanEmplace = TrueAlias< 714 absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>, 715 absl::enable_if_t< 716 Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>, 717 absl::enable_if_t<std::is_constructible<absl::decay_t<F>, Args...>::value>>; 718 719 /*SFINAE constraints for the conversion-assign operator.*/ 720 template <class Sig, class F, 721 class = absl::enable_if_t< 722 !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>> 723 using CanAssign = TrueAlias< 724 absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>, 725 absl::enable_if_t< 726 Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>, 727 absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>; 728 729 /*SFINAE constraints for the reference-wrapper conversion-assign operator.*/ 730 template <class Sig, class F> 731 using CanAssignReferenceWrapper = TrueAlias< 732 absl::enable_if_t< 733 Impl<Sig>::template CallIsValid<std::reference_wrapper<F>>::value>, 734 absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept< 735 std::reference_wrapper<F>>::value>>; 736 737 //////////////////////////////////////////////////////////////////////////////// 738 // 739 // The constraint for checking whether or not a call meets the noexcept 740 // callability requirements. This is a preprocessor macro because specifying it 741 // this way as opposed to a disjunction/branch can improve the user-side error 742 // messages and avoids an instantiation of std::is_nothrow_invocable_r in the 743 // cases where the user did not specify a noexcept function type. 744 // 745 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT(inv_quals, noex) \ 746 ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex(inv_quals) 747 748 // The disjunction below is because we can't rely on std::is_nothrow_invocable_r 749 // to give the right result when ReturnType is non-moveable in toolchains that 750 // don't treat non-moveable result types correctly. For example this was the 751 // case in libc++ before commit c3a24882 (2022-05). 752 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true(inv_quals) \ 753 absl::enable_if_t<absl::disjunction< \ 754 std::is_nothrow_invocable_r< \ 755 ReturnType, UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \ 756 P...>, \ 757 std::conjunction< \ 758 std::is_nothrow_invocable< \ 759 UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>, \ 760 std::is_same< \ 761 ReturnType, \ 762 absl::base_internal::invoke_result_t< \ 763 UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \ 764 P...>>>>::value> 765 766 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false(inv_quals) 767 // 768 //////////////////////////////////////////////////////////////////////////////// 769 770 // A macro to generate partial specializations of Impl with the different 771 // combinations of supported cv/reference qualifiers and noexcept specifier. 772 // 773 // Here, `cv` are the cv-qualifiers if any, `ref` is the ref-qualifier if any, 774 // inv_quals is the reference type to be used when invoking the target, and 775 // noex is "true" if the function type is noexcept, or false if it is not. 776 // 777 // The CallIsValid condition is more complicated than simply using 778 // absl::base_internal::is_invocable_r because we can't rely on it to give the 779 // right result when ReturnType is non-moveable in toolchains that don't treat 780 // non-moveable result types correctly. For example this was the case in libc++ 781 // before commit c3a24882 (2022-05). 782 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, noex) \ 783 template <class ReturnType, class... P> \ 784 class Impl<ReturnType(P...) cv ref ABSL_INTERNAL_NOEXCEPT_SPEC(noex)> \ 785 : public CoreImpl<noex, ReturnType, P...> { \ 786 public: \ 787 /*The base class, which contains the datamembers and core operations*/ \ 788 using Core = CoreImpl<noex, ReturnType, P...>; \ 789 \ 790 /*SFINAE constraint to check if F is invocable with the proper signature*/ \ 791 template <class F> \ 792 using CallIsValid = TrueAlias<absl::enable_if_t<absl::disjunction< \ 793 absl::base_internal::is_invocable_r<ReturnType, \ 794 absl::decay_t<F> inv_quals, P...>, \ 795 std::is_same<ReturnType, \ 796 absl::base_internal::invoke_result_t< \ 797 absl::decay_t<F> inv_quals, P...>>>::value>>; \ 798 \ 799 /*SFINAE constraint to check if F is nothrow-invocable when necessary*/ \ 800 template <class F> \ 801 using CallIsNoexceptIfSigIsNoexcept = \ 802 TrueAlias<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT(inv_quals, \ 803 noex)>; \ 804 \ 805 /*Put the AnyInvocable into an empty state.*/ \ 806 Impl() = default; \ 807 \ 808 /*The implementation of a conversion-constructor from "f*/ \ 809 /*This forwards to Core, attaching inv_quals so that the base class*/ \ 810 /*knows how to properly type-erase the invocation.*/ \ 811 template <class F> \ 812 explicit Impl(ConversionConstruct, F&& f) \ 813 : Core(TypedConversionConstruct< \ 814 typename std::decay<F>::type inv_quals>(), \ 815 std::forward<F>(f)) {} \ 816 \ 817 /*Forward along the in-place construction parameters.*/ \ 818 template <class T, class... Args> \ 819 explicit Impl(absl::in_place_type_t<T>, Args&&... args) \ 820 : Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \ 821 std::forward<Args>(args)...) {} \ 822 \ 823 /*Raises a fatal error when the AnyInvocable is invoked after a move*/ \ 824 static ReturnType InvokedAfterMove( \ 825 TypeErasedState*, \ 826 ForwardedParameterType<P>...) noexcept(noex) { \ 827 ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move"); \ 828 std::terminate(); \ 829 } \ 830 \ 831 InvokerType<noex, ReturnType, P...>* ExtractInvoker() cv { \ 832 using QualifiedTestType = int cv ref; \ 833 auto* invoker = this->invoker_; \ 834 if (!std::is_const<QualifiedTestType>::value && \ 835 std::is_rvalue_reference<QualifiedTestType>::value) { \ 836 ABSL_ASSERT([this]() { \ 837 /* We checked that this isn't const above, so const_cast is safe */ \ 838 const_cast<Impl*>(this)->invoker_ = InvokedAfterMove; \ 839 return this->HasValue(); \ 840 }()); \ 841 } \ 842 return invoker; \ 843 } \ 844 \ 845 /*The actual invocation operation with the proper signature*/ \ 846 ReturnType operator()(P... args) cv ref noexcept(noex) { \ 847 assert(this->invoker_ != nullptr); \ 848 return this->ExtractInvoker()( \ 849 const_cast<TypeErasedState*>(&this->state_), \ 850 static_cast<ForwardedParameterType<P>>(args)...); \ 851 } \ 852 } 853 854 // Define the `noexcept(true)` specialization only for C++17 and beyond, when 855 // `noexcept` is part of the type system. 856 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L 857 // A convenience macro that defines specializations for the noexcept(true) and 858 // noexcept(false) forms, given the other properties. 859 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals) \ 860 ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false); \ 861 ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, true) 862 #else 863 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals) \ 864 ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false) 865 #endif 866 867 // Non-ref-qualified partial specializations 868 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, , &); 869 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, , const&); 870 871 // Lvalue-ref-qualified partial specializations 872 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &, &); 873 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &, const&); 874 875 // Rvalue-ref-qualified partial specializations 876 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &&, &&); 877 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &&, const&&); 878 879 // Undef the detail-only macros. 880 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL 881 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL_ 882 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false 883 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true 884 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT 885 #undef ABSL_INTERNAL_NOEXCEPT_SPEC 886 887 } // namespace internal_any_invocable 888 ABSL_NAMESPACE_END 889 } // namespace absl 890 891 #endif // ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_ 892