#include #include #include #include SCENARIO("Observer Pointer initialization and construction", "[observer_ptr]") { GIVEN("An empty context") { WHEN("constructing by default") { auto ptr = kstd::observer_ptr{}; THEN("the observer pointer is null") { REQUIRE_FALSE(ptr); } } WHEN("constructing from a nullptr") { auto ptr = kstd::observer_ptr{nullptr}; THEN("the observer pointer is null") { REQUIRE_FALSE(ptr); } } WHEN("constructing from a raw pointer") { auto value = 1; auto ptr = kstd::observer_ptr{&value}; THEN("the observer pointer is not null") { REQUIRE(ptr); } THEN("the observer pointer points to the correct object") { REQUIRE(&*ptr == &value); } } WHEN("copy constructing from an existing observer pointer") { auto value = 1; auto ptr = kstd::observer_ptr{&value}; auto copy = ptr; THEN("the new observer pointer points to the same object as the other observer pointer") { REQUIRE(&*copy == &value); } } WHEN("copy constructing from an existing observer pointer with a compatible type") { struct A { }; struct B : A { }; auto value = B{}; auto ptr = kstd::observer_ptr(&value); auto copy = kstd::observer_ptr(ptr); THEN("the new observer pointer points to the same object as the other observer pointer") { REQUIRE(&*copy == &value); } } WHEN("copy assigning from an existing observer pointer") { auto value = 1; auto ptr = kstd::observer_ptr{&value}; auto copy = ptr; THEN("the new observer pointer points to the same object as the other observer pointer") { REQUIRE(&*copy == &value); } } WHEN("move constructing from an existing observer pointer") { auto value = 1; auto ptr = kstd::observer_ptr{&value}; auto copy = std::move(ptr); THEN("the new observer pointer points to the same object as the other observer pointer") { REQUIRE(&*copy == &value); } } WHEN("move assigning from an existing observer pointer") { auto value = 1; auto ptr = kstd::observer_ptr{&value}; auto copy = std::move(ptr); THEN("the new observer pointer points to the same object as the other observer pointer") { REQUIRE(&*copy == &value); } } } } SCENARIO("Observer pointer modifiers", "[observer_ptr]") { GIVEN("A non-null observer pointer") { auto value = 1; auto ptr = kstd::observer_ptr{&value}; WHEN("releasing the observer pointer") { auto raw_ptr = ptr.release(); THEN("the observer pointer is null") { REQUIRE_FALSE(ptr); } THEN("the returned pointer points to the correct object") { REQUIRE(raw_ptr == &value); } } WHEN("resetting the observer pointer to nullptr") { ptr.reset(); THEN("the observer pointer is null") { REQUIRE_FALSE(ptr); } } WHEN("resetting the observer pointer to a new object") { auto other_value = 2; ptr.reset(&other_value); THEN("the observer pointer points to the new object") { REQUIRE(&*ptr == &other_value); } } WHEN("swapping it with another observer pointer") { auto other_value = 2; auto other_ptr = kstd::observer_ptr{&other_value}; ptr.swap(other_ptr); THEN("the observer pointer points to the other object") { REQUIRE(&*ptr == &other_value); } THEN("the other observer pointer points to the original object") { REQUIRE(&*other_ptr == &value); } } } } SCENARIO("Observer pointer observers", "[observer_ptr]") { GIVEN("A non-null observer pointer") { struct A { int value{}; constexpr auto operator<=>(A const & other) const noexcept = default; }; auto value = A{1}; auto ptr = kstd::observer_ptr{&value}; WHEN("getting the raw pointer") { auto raw_ptr = ptr.get(); THEN("the raw pointer points to the correct object") { REQUIRE(raw_ptr == &value); } } WHEN("dereferencing the observer pointer") { auto dereferenced = *ptr; THEN("the dereferenced value is the correct value") { REQUIRE(dereferenced == value); } } WHEN("writing through the observer pointer with the arrow operator") { ptr->value = 2; THEN("the value is updated") { REQUIRE(value.value == 2); } } WHEN("converting the observer pointer to a raw pointer") { auto raw_ptr = static_cast(ptr); THEN("the raw pointer points to the correct object") { REQUIRE(raw_ptr == &value); } } } }