diff options
author | Abseil Team <absl-team@google.com> | 2023-03-06 10:26:02 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-03-06 10:27:01 -0800 |
commit | dc44b95ab0cc988afd225d0eb9f7021f96fcd2b6 (patch) | |
tree | 3899b6f828ee9a5138ded9087cf3be1a5f84f6f3 /absl/functional | |
parent | 807763a7f57dcf0ba4af7c3b218013e8f525e811 (diff) |
Support lvalue references to incomplete types as `FunctionRef` parameters.
PiperOrigin-RevId: 514451518
Change-Id: Ic1391374c7bff08ba437ac0410631d1f701bb9ed
Diffstat (limited to 'absl/functional')
-rw-r--r-- | absl/functional/function_ref_test.cc | 10 | ||||
-rw-r--r-- | absl/functional/internal/function_ref.h | 21 |
2 files changed, 22 insertions, 9 deletions
diff --git a/absl/functional/function_ref_test.cc b/absl/functional/function_ref_test.cc index 412027cd..d0923fdd 100644 --- a/absl/functional/function_ref_test.cc +++ b/absl/functional/function_ref_test.cc @@ -253,6 +253,16 @@ TEST(FunctionRef, PassByValueTypes) { } } +TEST(FunctionRef, ReferenceToIncompleteType) { + struct IncompleteType; + auto test = [](IncompleteType&) {}; + absl::FunctionRef<void(IncompleteType&)> ref(test); + + struct IncompleteType {}; + IncompleteType obj; + ref(obj); +} + } // namespace ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/functional/internal/function_ref.h b/absl/functional/internal/function_ref.h index b5bb8b43..a1ddbb0c 100644 --- a/absl/functional/internal/function_ref.h +++ b/absl/functional/internal/function_ref.h @@ -40,18 +40,21 @@ union VoidPtr { // Chooses the best type for passing T as an argument. // Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are // passed by value. +template <typename T, + bool IsLValueReference = std::is_lvalue_reference<T>::value> +struct PassByValue : std::false_type {}; + template <typename T> -constexpr bool PassByValue() { - return !std::is_lvalue_reference<T>::value && - absl::is_trivially_copy_constructible<T>::value && - absl::is_trivially_copy_assignable< - typename std::remove_cv<T>::type>::value && - std::is_trivially_destructible<T>::value && - sizeof(T) <= 2 * sizeof(void*); -} +struct PassByValue<T, /*IsLValueReference=*/false> + : std::integral_constant<bool, + absl::is_trivially_copy_constructible<T>::value && + absl::is_trivially_copy_assignable< + typename std::remove_cv<T>::type>::value && + std::is_trivially_destructible<T>::value && + sizeof(T) <= 2 * sizeof(void*)> {}; template <typename T> -struct ForwardT : std::conditional<PassByValue<T>(), T, T&&> {}; +struct ForwardT : std::conditional<PassByValue<T>::value, T, T&&> {}; // An Invoker takes a pointer to the type-erased invokable object, followed by // the arguments that the invokable object expects. |