"Fossies" - the Fresh Open Source Software Archive

Member "abseil-cpp-20230802.1/absl/functional/internal/any_invocable.h" (18 Sep 2023, 40183 Bytes) of package /linux/misc/abseil-cpp-20230802.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "any_invocable.h" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20230125.3_vs_20230802.0.

    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 <exception>
   60 #include <functional>
   61 #include <initializer_list>
   62 #include <memory>
   63 #include <new>
   64 #include <type_traits>
   65 #include <utility>
   66 
   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 ignored "-Wstrict-aliasing"
  219 #pragma GCC diagnostic push
  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 ignored "-Wpragmas"
  530 #pragma GCC diagnostic ignored "-Waddress"
  531 #pragma GCC diagnostic ignored "-Wnonnull-compare"
  532 #pragma GCC diagnostic push
  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_