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