| |
| |
|
|
| #include <string> |
|
|
| #include <catch2/catch_test_macros.hpp> |
|
|
| #include "common/unique_function.h" |
|
|
| namespace { |
| struct Noisy { |
| Noisy() : state{"Default constructed"} {} |
| Noisy(Noisy&& rhs) noexcept : state{"Move constructed"} { |
| rhs.state = "Moved away"; |
| } |
| Noisy& operator=(Noisy&& rhs) noexcept { |
| state = "Move assigned"; |
| rhs.state = "Moved away"; |
| return *this; |
| } |
| Noisy(const Noisy&) : state{"Copied constructed"} {} |
| Noisy& operator=(const Noisy&) { |
| state = "Copied assigned"; |
| return *this; |
| } |
|
|
| std::string state; |
| }; |
| } |
|
|
| TEST_CASE("UniqueFunction", "[common]") { |
| SECTION("Capture reference") { |
| int value = 0; |
| Common::UniqueFunction<void> func = [&value] { value = 5; }; |
| func(); |
| REQUIRE(value == 5); |
| } |
| SECTION("Capture pointer") { |
| int value = 0; |
| int* pointer = &value; |
| Common::UniqueFunction<void> func = [pointer] { *pointer = 5; }; |
| func(); |
| REQUIRE(value == 5); |
| } |
| SECTION("Move object") { |
| Noisy noisy; |
| REQUIRE(noisy.state == "Default constructed"); |
|
|
| Common::UniqueFunction<void> func = [noisy_inner = std::move(noisy)] { |
| REQUIRE(noisy_inner.state == "Move constructed"); |
| }; |
| REQUIRE(noisy.state == "Moved away"); |
| func(); |
| } |
| SECTION("Move construct function") { |
| int value = 0; |
| Common::UniqueFunction<void> func = [&value] { value = 5; }; |
| Common::UniqueFunction<void> new_func = std::move(func); |
| new_func(); |
| REQUIRE(value == 5); |
| } |
| SECTION("Move assign function") { |
| int value = 0; |
| Common::UniqueFunction<void> func = [&value] { value = 5; }; |
| Common::UniqueFunction<void> new_func; |
| new_func = std::move(func); |
| new_func(); |
| REQUIRE(value == 5); |
| } |
| SECTION("Default construct then assign function") { |
| int value = 0; |
| Common::UniqueFunction<void> func; |
| func = [&value] { value = 5; }; |
| func(); |
| REQUIRE(value == 5); |
| } |
| SECTION("Pass arguments") { |
| int result = 0; |
| Common::UniqueFunction<void, int, int> func = [&result](int a, int b) { result = a + b; }; |
| func(5, 4); |
| REQUIRE(result == 9); |
| } |
| SECTION("Pass arguments and return value") { |
| Common::UniqueFunction<int, int, int> func = [](int a, int b) { return a + b; }; |
| REQUIRE(func(5, 4) == 9); |
| } |
| SECTION("Destructor") { |
| int num_destroyed = 0; |
| struct Foo { |
| Foo(int* num_) : num{num_} {} |
| Foo(Foo&& rhs) : num{std::exchange(rhs.num, nullptr)} {} |
| Foo(const Foo&) = delete; |
|
|
| ~Foo() { |
| if (num) { |
| ++*num; |
| } |
| } |
|
|
| int* num = nullptr; |
| }; |
| Foo object{&num_destroyed}; |
| { |
| Common::UniqueFunction<void> func = [object_inner = std::move(object)] {}; |
| REQUIRE(num_destroyed == 0); |
| } |
| REQUIRE(num_destroyed == 1); |
| } |
| } |
|
|