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