diff options
author | Jacques Lucke <jacques@blender.org> | 2021-02-23 13:47:01 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-02-23 13:52:06 +0300 |
commit | aa4882506c9acb5483b506c5e1d1569ca8cf5dd3 (patch) | |
tree | bc5f8188b267e4a3caf173810d6e1778a7cc9dcd /source/blender/blenlib/tests | |
parent | b2e1b13abde787c2aad97d5c317357cf84360bdb (diff) |
BLI: new FunctionRef type
Using `FunctionRef` is better than using `std::function`, templates and c function
pointers in some cases. The trade offs are explained in more detail in code documentation.
The following are some of the main benefits of using `FunctionRef`:
* It is convenient to use with all kinds of callables.
* It is cheaper to construct, copy and (possibly) call compared to `std::function`.
* Functions taking a `FunctionRef` as parameter don't need to be declared
in header files (as is necessary when using templates usually).
Differential Revision: https://developer.blender.org/D10476
Diffstat (limited to 'source/blender/blenlib/tests')
-rw-r--r-- | source/blender/blenlib/tests/BLI_function_ref_test.cc | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/source/blender/blenlib/tests/BLI_function_ref_test.cc b/source/blender/blenlib/tests/BLI_function_ref_test.cc new file mode 100644 index 00000000000..cdcbccc72e8 --- /dev/null +++ b/source/blender/blenlib/tests/BLI_function_ref_test.cc @@ -0,0 +1,102 @@ +/* Apache License, Version 2.0 */ + +#include "BLI_function_ref.hh" + +#include "testing/testing.h" + +namespace blender::tests { + +static int perform_binary_operation(int a, int b, FunctionRef<int(int, int)> operation) +{ + return operation(a, b); +} + +TEST(function_ref, StatelessLambda) +{ + const int result = perform_binary_operation(4, 6, [](int a, int b) { return a - b; }); + EXPECT_EQ(result, -2); +} + +TEST(function_ref, StatefullLambda) +{ + const int factor = 10; + const int result = perform_binary_operation( + 2, 3, [&](int a, int b) { return factor * (a + b); }); + EXPECT_EQ(result, 50); +} + +static int add_two_numbers(int a, int b) +{ + return a + b; +} + +TEST(function_ref, StandaloneFunction) +{ + const int result = perform_binary_operation(10, 5, add_two_numbers); + EXPECT_EQ(result, 15); +} + +TEST(function_ref, ConstantFunction) +{ + auto f = []() { return 42; }; + FunctionRef<int()> ref = f; + EXPECT_EQ(ref(), 42); +} + +TEST(function_ref, MutableStatefullLambda) +{ + int counter = 0; + auto f = [&]() mutable { return counter++; }; + FunctionRef<int()> ref = f; + EXPECT_EQ(ref(), 0); + EXPECT_EQ(ref(), 1); + EXPECT_EQ(ref(), 2); +} + +TEST(function_ref, Null) +{ + FunctionRef<int()> ref; + EXPECT_FALSE(ref); + + auto f = []() { return 1; }; + ref = f; + EXPECT_TRUE(ref); + + ref = {}; + EXPECT_FALSE(ref); +} + +TEST(function_ref, CopyDoesNotReferenceFunctionRef) +{ + auto f1 = []() { return 1; }; + auto f2 = []() { return 2; }; + FunctionRef<int()> x = f1; + FunctionRef<int()> y = x; + x = f2; + EXPECT_EQ(y(), 1); +} + +TEST(function_ref, CopyDoesNotReferenceFunctionRef2) +{ + auto f = []() { return 1; }; + FunctionRef<int()> x; + FunctionRef<int()> y = f; + FunctionRef<int()> z = static_cast<const FunctionRef<int()> &&>(y); + x = z; + y = {}; + EXPECT_EQ(x(), 1); +} + +TEST(function_ref, ReferenceAnotherFunctionRef) +{ + auto f1 = []() { return 1; }; + auto f2 = []() { return 2; }; + FunctionRef<int()> x = f1; + auto f3 = [&]() { return x(); }; + FunctionRef<int()> y = f3; + EXPECT_EQ(y(), 1); + x = f2; + EXPECT_EQ(y(), 2); +} + +} // namespace blender::tests |