diff options
Diffstat (limited to 'absl/functional/internal/any_invocable.h')
-rw-r--r-- | absl/functional/internal/any_invocable.h | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/absl/functional/internal/any_invocable.h b/absl/functional/internal/any_invocable.h index 35b389d1..d41b7e56 100644 --- a/absl/functional/internal/any_invocable.h +++ b/absl/functional/internal/any_invocable.h @@ -56,6 +56,7 @@ #include <cassert> #include <cstddef> #include <cstring> +#include <exception> #include <functional> #include <initializer_list> #include <memory> @@ -66,6 +67,7 @@ #include "absl/base/config.h" #include "absl/base/internal/invoke.h" #include "absl/base/macros.h" +#include "absl/base/optimization.h" #include "absl/meta/type_traits.h" #include "absl/utility/utility.h" @@ -281,7 +283,7 @@ void LocalManagerNontrivial(FunctionToCall operation, from_object.~T(); // Must not throw. // NOLINT return; } - ABSL_INTERNAL_UNREACHABLE; + ABSL_UNREACHABLE(); } // The invoker that is used when a target function is in local storage @@ -319,7 +321,7 @@ inline void RemoteManagerTrivial(FunctionToCall operation, #endif // __cpp_sized_deallocation return; } - ABSL_INTERNAL_UNREACHABLE; + ABSL_UNREACHABLE(); } // The manager that is used when a target function is in remote storage and the @@ -341,7 +343,7 @@ void RemoteManagerNontrivial(FunctionToCall operation, ::delete static_cast<T*>(from->remote.target); // Must not throw. return; } - ABSL_INTERNAL_UNREACHABLE; + ABSL_UNREACHABLE(); } // The invoker that is used when a target function is in remote storage @@ -486,7 +488,7 @@ class CoreImpl { // object. Clear(); - // Perform the actual move/destory operation on the target function. + // Perform the actual move/destroy operation on the target function. other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_); manager_ = other.manager_; invoker_ = other.invoker_; @@ -809,11 +811,34 @@ using CanAssignReferenceWrapper = TrueAlias< : Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \ std::forward<Args>(args)...) {} \ \ + /*Raises a fatal error when the AnyInvocable is invoked after a move*/ \ + static ReturnType InvokedAfterMove( \ + TypeErasedState*, \ + ForwardedParameterType<P>...) noexcept(noex) { \ + ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move"); \ + std::terminate(); \ + } \ + \ + InvokerType<noex, ReturnType, P...>* ExtractInvoker() cv { \ + using QualifiedTestType = int cv ref; \ + auto* invoker = this->invoker_; \ + if (!std::is_const<QualifiedTestType>::value && \ + std::is_rvalue_reference<QualifiedTestType>::value) { \ + ABSL_ASSERT([this]() { \ + /* We checked that this isn't const above, so const_cast is safe */ \ + const_cast<Impl*>(this)->invoker_ = InvokedAfterMove; \ + return this->HasValue(); \ + }()); \ + } \ + return invoker; \ + } \ + \ /*The actual invocation operation with the proper signature*/ \ ReturnType operator()(P... args) cv ref noexcept(noex) { \ assert(this->invoker_ != nullptr); \ - return this->invoker_(const_cast<TypeErasedState*>(&this->state_), \ - static_cast<ForwardedParameterType<P>>(args)...); \ + return this->ExtractInvoker()( \ + const_cast<TypeErasedState*>(&this->state_), \ + static_cast<ForwardedParameterType<P>>(args)...); \ } \ } |