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