diff options
author | Abseil Team <absl-team@google.com> | 2022-10-11 10:27:17 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-10-11 10:28:00 -0700 |
commit | 73789eb0689071b0b02b00cb3daed9f224ff1a10 (patch) | |
tree | b6fec5c27f8d6044655b85b021d5702e5f3b73e8 /absl/functional/internal | |
parent | 845610e80b66aa3d834f4d1b401133919bf7fadb (diff) |
Detects accidental multiple invocations of AnyInvocable<R(...)&&>::operator()&& by producing an error in debug mode, and clarifies that the behavior is undefined in the general case.
PiperOrigin-RevId: 480392976
Change-Id: I2d4c6f213fa7c8747f125c9735272a8e47b9214b
Diffstat (limited to 'absl/functional/internal')
-rw-r--r-- | absl/functional/internal/any_invocable.h | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/absl/functional/internal/any_invocable.h b/absl/functional/internal/any_invocable.h index 35b389d1..8fce4bf6 100644 --- a/absl/functional/internal/any_invocable.h +++ b/absl/functional/internal/any_invocable.h @@ -809,11 +809,31 @@ using CanAssignReferenceWrapper = TrueAlias< : Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \ std::forward<Args>(args)...) {} \ \ + 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_HARDENING_ASSERT([this]() { \ + /* We checked that this isn't const above, so const_cast is safe */ \ + const_cast<Impl*>(this)->invoker_ = \ + [](TypeErasedState*, \ + ForwardedParameterType<P>...) noexcept(noex) -> ReturnType { \ + ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move"); \ + std::terminate(); \ + }; \ + 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)...); \ } \ } |