// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include #include #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; }; } // Anonymous namespace TEST_CASE("UniqueFunction", "[common]") { SECTION("Capture reference") { int value = 0; Common::UniqueFunction func = [&value] { value = 5; }; func(); REQUIRE(value == 5); } SECTION("Capture pointer") { int value = 0; int* pointer = &value; Common::UniqueFunction func = [pointer] { *pointer = 5; }; func(); REQUIRE(value == 5); } SECTION("Move object") { Noisy noisy; REQUIRE(noisy.state == "Default constructed"); Common::UniqueFunction func = [noisy = std::move(noisy)] { REQUIRE(noisy.state == "Move constructed"); }; REQUIRE(noisy.state == "Moved away"); func(); } SECTION("Move construct function") { int value = 0; Common::UniqueFunction func = [&value] { value = 5; }; Common::UniqueFunction new_func = std::move(func); new_func(); REQUIRE(value == 5); } SECTION("Move assign function") { int value = 0; Common::UniqueFunction func = [&value] { value = 5; }; Common::UniqueFunction new_func; new_func = std::move(func); new_func(); REQUIRE(value == 5); } SECTION("Default construct then assign function") { int value = 0; Common::UniqueFunction func; func = [&value] { value = 5; }; func(); REQUIRE(value == 5); } SECTION("Pass arguments") { int result = 0; Common::UniqueFunction func = [&result](int a, int b) { result = a + b; }; func(5, 4); REQUIRE(result == 9); } SECTION("Pass arguments and return value") { Common::UniqueFunction 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 func = [object = std::move(object)] {}; REQUIRE(num_destroyed == 0); } REQUIRE(num_destroyed == 1); } }