From dc44b95ab0cc988afd225d0eb9f7021f96fcd2b6 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 6 Mar 2023 10:26:02 -0800 Subject: Support lvalue references to incomplete types as `FunctionRef` parameters. PiperOrigin-RevId: 514451518 Change-Id: Ic1391374c7bff08ba437ac0410631d1f701bb9ed --- absl/functional/internal/function_ref.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'absl/functional/internal/function_ref.h') 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 ::value> +struct PassByValue : std::false_type {}; + template -constexpr bool PassByValue() { - return !std::is_lvalue_reference::value && - absl::is_trivially_copy_constructible::value && - absl::is_trivially_copy_assignable< - typename std::remove_cv::type>::value && - std::is_trivially_destructible::value && - sizeof(T) <= 2 * sizeof(void*); -} +struct PassByValue + : std::integral_constant::value && + absl::is_trivially_copy_assignable< + typename std::remove_cv::type>::value && + std::is_trivially_destructible::value && + sizeof(T) <= 2 * sizeof(void*)> {}; template -struct ForwardT : std::conditional(), T, T&&> {}; +struct ForwardT : std::conditional::value, T, T&&> {}; // An Invoker takes a pointer to the type-erased invokable object, followed by // the arguments that the invokable object expects. -- cgit v1.2.3 From 8bd7178b14ea61972f8b04e9a9352bc4a4666cfb Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 24 Apr 2023 08:04:04 -0700 Subject: Adds template specialization for nullptr assertion of absl::AnyInvocable types. PiperOrigin-RevId: 526644558 Change-Id: I050162c2c0d667c32f7e11f51201054cca52667d --- absl/functional/BUILD.bazel | 2 ++ absl/functional/CMakeLists.txt | 1 + absl/functional/function_ref_test.cc | 20 ++++++++++++++++++++ absl/functional/internal/function_ref.h | 7 +++++++ 4 files changed, 30 insertions(+) (limited to 'absl/functional/internal/function_ref.h') diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel index c4fbce98..4ceac539 100644 --- a/absl/functional/BUILD.bazel +++ b/absl/functional/BUILD.bazel @@ -92,6 +92,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + ":any_invocable", "//absl/base:base_internal", "//absl/base:core_headers", "//absl/meta:type_traits", @@ -104,6 +105,7 @@ cc_test( srcs = ["function_ref_test.cc"], copts = ABSL_TEST_COPTS, deps = [ + ":any_invocable", ":function_ref", "//absl/container:test_instance_tracker", "//absl/memory", diff --git a/absl/functional/CMakeLists.txt b/absl/functional/CMakeLists.txt index c0f6eaaa..628b2ffc 100644 --- a/absl/functional/CMakeLists.txt +++ b/absl/functional/CMakeLists.txt @@ -90,6 +90,7 @@ absl_cc_library( DEPS absl::base_internal absl::core_headers + absl::any_invocable absl::meta PUBLIC ) diff --git a/absl/functional/function_ref_test.cc b/absl/functional/function_ref_test.cc index d0923fdd..f91e15e0 100644 --- a/absl/functional/function_ref_test.cc +++ b/absl/functional/function_ref_test.cc @@ -20,6 +20,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/container/internal/test_instance_tracker.h" +#include "absl/functional/any_invocable.h" #include "absl/memory/memory.h" namespace absl { @@ -157,6 +158,25 @@ TEST(FunctionRef, NullMemberPtrAssertFails) { EXPECT_DEBUG_DEATH({ FunctionRef ref(mem_ptr); }, ""); } +TEST(FunctionRef, NullStdFunctionAssertPasses) { + std::function function = []() {}; + FunctionRef ref(function); +} + +TEST(FunctionRef, NullStdFunctionAssertFails) { + std::function function = nullptr; + EXPECT_DEBUG_DEATH({ FunctionRef ref(function); }, ""); +} + +TEST(FunctionRef, NullAnyInvocableAssertPasses) { + AnyInvocable invocable = []() {}; + FunctionRef ref(invocable); +} +TEST(FunctionRef, NullAnyInvocableAssertFails) { + AnyInvocable invocable = nullptr; + EXPECT_DEBUG_DEATH({ FunctionRef ref(invocable); }, ""); +} + #endif // GTEST_HAS_DEATH_TEST TEST(FunctionRef, CopiesAndMovesPerPassByValue) { diff --git a/absl/functional/internal/function_ref.h b/absl/functional/internal/function_ref.h index a1ddbb0c..1cd34a3c 100644 --- a/absl/functional/internal/function_ref.h +++ b/absl/functional/internal/function_ref.h @@ -20,6 +20,7 @@ #include #include "absl/base/internal/invoke.h" +#include "absl/functional/any_invocable.h" #include "absl/meta/type_traits.h" namespace absl { @@ -90,6 +91,12 @@ void AssertNonNull(const std::function& f) { (void)f; } +template +void AssertNonNull(const AnyInvocable& f) { + assert(f != nullptr); + (void)f; +} + template void AssertNonNull(const F&) {} -- cgit v1.2.3