#include <iostream>
#include <stack>
#include <memory>
template<typename T>
class Undo : public T {
private:
std::shared_ptr<std::stack<Undo>> history_ptr = std::make_shared<std::stack<Undo>>();
public:
template <typename... Args>
explicit Undo(const Args&... args): T(args ...) {}
void save() {
history_ptr->push(*this);
}
void undo() {
if (!history_ptr->empty()) {
*this = history_ptr->top();
history_ptr->pop();
}
}
};
class Foo {
public:
int a = 0;
std::string s;
Foo(const int _a, std::string _s): a(_a), s(std::move(_s)) {}
};
std::ostream &operator<<(std::ostream &out, const Foo &foo) {
out << "Foo(" << foo.a << ", \"" << foo.s << "\")";
return out;
}
int main() {
Undo<Foo> foo(1, "Hello World!");
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.a = 6661313;
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.s = "Lakad Matataaag!";
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.a = 9000;
foo.s = "Normalin, Normalin!";
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.a = 12345678;
foo.s = "Da next lebel play!";
std::cout << "Current\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
return 0;
}