From 328b39335ef82248eb4a8af16251247763be5a2f Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 1 Apr 2021 12:33:41 +0200 Subject: BLI: add call_safe method for FunctionRef This is useful to avoid nullity checks in some places. --- source/blender/blenlib/BLI_function_ref.hh | 24 +++++++++++++++++++++ .../blender/blenlib/tests/BLI_function_ref_test.cc | 25 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'source/blender/blenlib') diff --git a/source/blender/blenlib/BLI_function_ref.hh b/source/blender/blenlib/BLI_function_ref.hh index 57fffdc09b4..38e1ba593c5 100644 --- a/source/blender/blenlib/BLI_function_ref.hh +++ b/source/blender/blenlib/BLI_function_ref.hh @@ -16,6 +16,7 @@ #pragma once +#include #include #include @@ -139,6 +140,29 @@ template class FunctionRef { return callback_(callable_, std::forward(params)...); } + using OptionalReturnValue = std::conditional_t, void, std::optional>; + + /** + * Calls the referenced function if it is available. + * The return value is of type `std::optional` if `Ret` is not `void`. + * Otherwise the return type is `void`. + */ + OptionalReturnValue call_safe(Params... params) const + { + if constexpr (std::is_void_v) { + if (callback_ == nullptr) { + return; + } + callback_(callable_, std::forward(params)...); + } + else { + if (callback_ == nullptr) { + return {}; + } + return callback_(callable_, std::forward(params)...); + } + } + /** * Returns true, when the `FunctionRef` references a function currently. * If this returns false, the `FunctionRef` must not be called. diff --git a/source/blender/blenlib/tests/BLI_function_ref_test.cc b/source/blender/blenlib/tests/BLI_function_ref_test.cc index cdcbccc72e8..74f5014142c 100644 --- a/source/blender/blenlib/tests/BLI_function_ref_test.cc +++ b/source/blender/blenlib/tests/BLI_function_ref_test.cc @@ -99,4 +99,29 @@ TEST(function_ref, ReferenceAnotherFunctionRef) EXPECT_EQ(y(), 2); } +TEST(function_ref, CallSafe) +{ + FunctionRef f; + EXPECT_FALSE(f.call_safe().has_value()); + auto func = []() { return 10; }; + f = func; + EXPECT_TRUE(f.call_safe().has_value()); + EXPECT_EQ(*f.call_safe(), 10); + f = {}; + EXPECT_FALSE(f.call_safe().has_value()); + BLI_STATIC_ASSERT((std::is_same_v>), ""); +} + +TEST(function_ref, CallSafeVoid) +{ + FunctionRef f; + BLI_STATIC_ASSERT((std::is_same_v), ""); + f.call_safe(); + int value = 0; + auto func = [&]() { value++; }; + f = func; + f.call_safe(); + EXPECT_EQ(value, 1); +} + } // namespace blender::tests -- cgit v1.2.3