/* Copyright 2013 Adobe Systems Incorporated Distributed under the MIT License (see license at http://stlab.adobe.com/licenses.html) This file is intended as example code and is not production quality. */ #include #include #include #include #include using namespace std; /******************************************************************************/ // Library template void draw(const T& x, ostream& out, size_t position) { out << string(position, ' ') << x << endl; } class object_t { public: template object_t(T x) : self_(new model(move(x))) { } object_t(const object_t& x) : self_(x.self_->copy_()) { } object_t(object_t&&) noexcept = default; object_t& operator=(const object_t& x) { object_t tmp(x); *this = move(tmp); return *this; } object_t& operator=(object_t&&) noexcept = default; friend void draw(const object_t& x, ostream& out, size_t position) { x.self_->draw_(out, position); } private: struct concept_t { virtual ~concept_t() = default; virtual concept_t* copy_() const = 0; virtual void draw_(ostream&, size_t) const = 0; }; template struct model : concept_t { model(T x) : data_(move(x)) { } concept_t* copy_() const { return new model(*this); } void draw_(ostream& out, size_t position) const { draw(data_, out, position); } T data_; }; unique_ptr self_; }; using document_t = vector; void draw(const document_t& x, ostream& out, size_t position) { out << string(position, ' ') << "" << endl; for (auto& e : x) draw(e, out, position + 2); out << string(position, ' ') << "" << endl; } using history_t = vector; void commit(history_t& x) { assert(x.size()); x.push_back(x.back()); } void undo(history_t& x) { assert(x.size()); x.pop_back(); } document_t& current(history_t& x) { assert(x.size()); return x.back(); } /******************************************************************************/ // Client class my_class_t { /* ... */ }; void draw(const my_class_t&, ostream& out, size_t position) { out << string(position, ' ') << "my_class_t" << endl; } int main() { history_t h(1); current(h).emplace_back(0); current(h).emplace_back(string("Hello!")); draw(current(h), cout, 0); cout << "--------------------------" << endl; commit(h); current(h).emplace_back(current(h)); current(h).emplace_back(my_class_t()); current(h)[1] = string("World"); draw(current(h), cout, 0); cout << "--------------------------" << endl; undo(h); draw(current(h), cout, 0); }