#include <catch2/catch.hpp> #include <alib/memory> #include <alib/utility> namespace { class Moveable { int& m_moves; int& m_copies; public: Moveable(int& moves, int& copies) : m_moves(moves), m_copies(copies) { m_moves = 0; m_copies = 0; } Moveable(const Moveable& src) : m_moves(src.m_moves), m_copies(src.m_copies) { m_copies++; } Moveable(Moveable&& src) : m_moves(src.m_moves), m_copies(src.m_copies) { m_moves++; } bool operator<(const Moveable&) const { return false; } }; class Moveable2 { int& m_moves; int& m_copies; public: Moveable2(int& moves, int& copies) : m_moves(moves), m_copies(copies) { m_moves = 0; m_copies = 0; } Moveable2(const Moveable2& src) : m_moves(src.m_moves), m_copies(src.m_copies) { m_copies++; } Moveable2(Moveable2&& src) : m_moves(src.m_moves), m_copies(src.m_copies) { m_moves++; } bool operator<(const Moveable2&) const { return false; } }; class Base { public: virtual Base* clone() const = 0; virtual ~Base ( ) { } }; class Derived : public Base { public: virtual Derived* clone() const override { return new Derived(*this); } virtual ~Derived ( ) override { } }; } TEST_CASE ( "Shared Ptr", "[unit][std][bits]" ) { SECTION ( "Shared Ptr" ) { { int moves; int copies; ext::cow_shared_ptr<Moveable> one(new Moveable(moves, copies)); CHECK(one.unique()); CHECK(moves == 0); CHECK(copies == 0); ext::cow_shared_ptr<Moveable> two(one); CHECK(!one.unique()); CHECK(moves == 0); CHECK(copies == 0); std::as_const(two).get(); ext::cow_shared_ptr<Moveable> three(std::move ( two ) ); std::as_const(three).get(); CHECK(!one.unique()); CHECK(moves == 0); CHECK(copies == 0); two = std::move ( three ) ; two.get(); CHECK(one.unique()); CHECK(moves == 0); CHECK(copies == 1); } { int moves; int copies; ext::cow_shared_ptr<Moveable2> one(new Moveable2(moves, copies)); CHECK(one.unique()); CHECK(moves == 0); CHECK(copies == 0); ext::cow_shared_ptr<Moveable2> two(one); CHECK(!one.unique()); CHECK(moves == 0); CHECK(copies == 0); std::as_const(two).get(); ext::cow_shared_ptr<Moveable2> three(std::move ( two ) ); std::as_const(three).get(); CHECK(!one.unique()); CHECK(moves == 0); CHECK(copies == 0); two = std::move ( three ) ; two.get(); CHECK(one.unique()); CHECK(moves == 0); CHECK(copies == 1); } { ext::cow_shared_ptr<Base> one(new Derived()); ext::cow_shared_ptr<Base> two(one); CHECK(!one.unique()); two.get(); CHECK(one.unique()); CHECK(two.unique()); CHECK(one.get() != two.get()); } } }