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