#include #include class IColumn : public COW { private: friend class COW; virtual MutablePtr clone() const = 0; virtual MutablePtr deepMutate() const { return shallowMutate(); } public: IColumn() = default; IColumn(const IColumn &) = default; virtual ~IColumn() = default; virtual int get() const = 0; virtual void set(int value) = 0; MutablePtr mutate() const && { return deepMutate(); } }; using ColumnPtr = IColumn::Ptr; using MutableColumnPtr = IColumn::MutablePtr; class ConcreteColumn : public COWHelper { private: friend class COWHelper; int data; explicit ConcreteColumn(int data_) : data(data_) {} ConcreteColumn(const ConcreteColumn &) = default; public: int get() const override { return data; } void set(int value) override { data = value; } }; class ColumnComposition : public COWHelper { private: friend class COWHelper; ConcreteColumn::WrappedPtr wrapped; explicit ColumnComposition(int data) : wrapped(ConcreteColumn::create(data)) {} ColumnComposition(const ColumnComposition &) = default; IColumn::MutablePtr deepMutate() const override { std::cerr << "Mutating\n"; auto res = shallowMutate(); res->wrapped = std::move(*wrapped).mutate(); return res; } public: int get() const override { return wrapped->get(); } void set(int value) override { wrapped->set(value); } }; int main(int, char **) { ColumnPtr x = ColumnComposition::create(1); ColumnPtr y = x; std::cerr << "values: " << x->get() << ", " << y->get() << "\n"; std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n"; std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n"; { MutableColumnPtr mut = std::move(*y).mutate(); mut->set(2); std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << ", " << mut->use_count() << "\n"; std::cerr << "addresses: " << x.get() << ", " << y.get() << ", " << mut.get() << "\n"; y = std::move(mut); } std::cerr << "values: " << x->get() << ", " << y->get() << "\n"; std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n"; std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n"; x = ColumnComposition::create(0); std::cerr << "values: " << x->get() << ", " << y->get() << "\n"; std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n"; std::cerr << "addresses: " << x.get() << ", " << y.get() << "\n"; { MutableColumnPtr mut = std::move(*y).mutate(); mut->set(3); std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << ", " << mut->use_count() << "\n"; std::cerr << "addresses: " << x.get() << ", " << y.get() << ", " << mut.get() << "\n"; y = std::move(mut); } std::cerr << "values: " << x->get() << ", " << y->get() << "\n"; std::cerr << "refcounts: " << x->use_count() << ", " << y->use_count() << "\n"; return 0; }