summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2023-03-06 10:26:02 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2023-03-06 10:27:01 -0800
commitdc44b95ab0cc988afd225d0eb9f7021f96fcd2b6 (patch)
tree3899b6f828ee9a5138ded9087cf3be1a5f84f6f3
parent807763a7f57dcf0ba4af7c3b218013e8f525e811 (diff)
Support lvalue references to incomplete types as `FunctionRef` parameters.
PiperOrigin-RevId: 514451518 Change-Id: Ic1391374c7bff08ba437ac0410631d1f701bb9ed
-rw-r--r--absl/functional/function_ref_test.cc10
-rw-r--r--absl/functional/internal/function_ref.h21
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.