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