BLI: improve FunctionRef constructor in case of a falsy callable
Previously, passing a falsy `std::function` (i.e. it is empty) or a null function pointer would result in a `FunctionRef` which is thruthy and thus appeared callable. Now, when the passed in callable is falsy, the resulting `FunctionRef` will be too. Pull Request: https://projects.blender.org/blender/blender/pulls/128823
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "BLI_build_config.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
/** \file
|
||||
@@ -119,6 +120,26 @@ template<typename Ret, typename... Params> class FunctionRef<Ret(Params...)> {
|
||||
: callback_(callback_fn<typename std::remove_reference_t<Callable>>),
|
||||
callable_(intptr_t(&callable))
|
||||
{
|
||||
if constexpr (std::is_constructible_v<bool, Callable>) {
|
||||
/* For some types, the compiler can be sure that the callable is always truthy. Good!
|
||||
Then
|
||||
* the entire check can be optimized away. */
|
||||
#if COMPILER_CLANG || COMPILER_GCC
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Waddress"
|
||||
# pragma GCC diagnostic ignored "-Wnonnull-compare"
|
||||
#endif
|
||||
/* Make sure the #FunctionRef is falsy if the callback is falsy.
|
||||
* That can happen when passing in null or empty std::function. */
|
||||
const bool is_truthy = bool(callable);
|
||||
if (!is_truthy) {
|
||||
callback_ = nullptr;
|
||||
callable_ = 0;
|
||||
}
|
||||
#if COMPILER_CLANG || COMPILER_GCC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -126,4 +126,30 @@ TEST(function_ref, OverloadSelection)
|
||||
EXPECT_EQ(overload_test(fn_2), 2);
|
||||
}
|
||||
|
||||
TEST(function_ref, FalsyStdFunction)
|
||||
{
|
||||
const std::function<void()> fn1;
|
||||
const std::function<void()> fn2 = [&]() {};
|
||||
const FunctionRef<void()> fn_ref1(fn1);
|
||||
const FunctionRef<void()> fn_ref2(fn2);
|
||||
EXPECT_FALSE(fn_ref1);
|
||||
EXPECT_TRUE(fn_ref2);
|
||||
|
||||
const FunctionRef<void()> fn_ref3(fn1);
|
||||
const FunctionRef<void()> fn_ref4(fn2);
|
||||
EXPECT_FALSE(fn_ref3);
|
||||
EXPECT_TRUE(fn_ref4);
|
||||
}
|
||||
|
||||
TEST(function_ref, FalsyFunctionPointer)
|
||||
{
|
||||
using Fn = void (*)();
|
||||
const Fn fn1 = nullptr;
|
||||
const Fn fn2 = []() {};
|
||||
const FunctionRef<void()> fn_ref1(fn1);
|
||||
const FunctionRef<void()> fn_ref2(fn2);
|
||||
EXPECT_FALSE(fn_ref1);
|
||||
EXPECT_TRUE(fn_ref2);
|
||||
}
|
||||
|
||||
} // namespace blender::tests
|
||||
|
||||
Reference in New Issue
Block a user