tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

any_invocable.h (35474B)


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