#include <iostream>
#include <memory>
#include <list>
class Base {
friend class BaseWrapper;
friend std::ostream & operator << (std::ostream &os, const Base &b) {
b.print(os);
return os;
}
virtual void print (std::ostream &os) const = 0;
virtual Base * clone () const = 0;
protected:
template <typename T> static Base * clone_impl (const T &t) {
return new T(t);
}
public:
virtual ~Base () {}
};
class Derived1 : public Base {
std::string s;
void print (std::ostream &os) const { os << s; }
Base * clone () const { return clone_impl(*this); }
public:
Derived1 () : s("D1") {}
};
class Derived2 : public Base {
int x;
std::string s;
double y;
void print (std::ostream &os) const { os << (x + y) << ":" << s; }
Base * clone () const { return clone_impl(*this); }
public:
Derived2 () : x(3), s("D2"), y(.14159) {}
};
class Derived3 : public Base {
std::string s;
void print (std::ostream &os) const { os << s; }
Base * clone () const { return clone_impl(*this); }
public:
Derived3 () : s("D3") {}
};
class BaseWrapper : public Base {
std::unique_ptr<Base> ptr;
void print (std::ostream &os) const { ptr->print(os); }
Base * clone () const { return ptr->clone(); }
public:
BaseWrapper (const Base &b) : ptr(b.clone()) {}
BaseWrapper (BaseWrapper &&b) { ptr.swap(b.ptr); }
};
typedef std::list<BaseWrapper> any_list;
int main ()
{
any_list l;
l.push_back(Derived1());
l.push_back(Derived2());
l.push_back(Derived3());
for (const auto &x : l) {
std::cout << " " << x;
}
std::cout << std::endl;
}