#include <vector>
#include <iostream>
#include <algorithm>

// TypeErasure is a concrete non-templated class respecting value
// semantic which holds any type conforming to a given interface.
class TypeErasure {
private:
    // Concept is an abstract base class corresponding
    // to the interface being enforced. This class can't
    // be templated on the stored type since it would
    // require that the TypeEreasure class be also templated
    // on the stored type, i.e. the impl pointer would
    // need to be templated.
    struct Concept {
        // Use a virtual destructor since the Model<T>
        // will be deleted through the Concept class.
        virtual ~Concept() {}
        virtual Concept* copy() const = 0;
        // Forwarding common interface functions to the
        // stored type.
        virtual void print() const = 0;
    };

    // The Model is an aggregate which implements the interface
    // defined by the Concept. In practice, the Model simply
    // forwards call to the wrapped object of type T.
    template <typename T>
    struct Model: Concept {
        explicit Model(const T& x) :
            data(x) {
        }
        Concept* copy() const {
            return new Model(data);
        }
        void print() const {
            data.print();
        }

        T data;	// Must have a print(data) defined somewhere.
    };

    // The impl member is a pointer to the instantiated Model<T>.
    // See the private implementation pattern for references on this.
    // Note that the impl pointer isn't templated. If it was, the
    // TypeErasure class would also require to be templated.
    Concept* impl;

public:
    // Constructor which takes any type T whose interface matches
    // the one enforced by Model<T>. Could include fundamental types.
    // The constructor is declared explicit to prevents it from
    // being invoked implicitly as a conversion.
    template <typename T>
    explicit TypeErasure(const T& x) :
        impl(new Model<T> (x)) {
    }

    ~TypeErasure() {
        delete impl;
    }

    // TypeErasure copy constructor is implemented by
    // copying the stored object behind the scene.
    TypeErasure(const TypeErasure& x) :
        impl(x.impl->copy()) {
    }

    // Pass by value for exception safety and to allow
    // compiler's optimizations.
    TypeErasure& operator=(TypeErasure x) {
        swap(x);
        return *this;
    }

    void swap(TypeErasure& other) {
        using std::swap;
        swap(impl, other.impl);
    }

    void print() const {
        impl->print();
    }
};

namespace std {
    template<>
    void swap<TypeErasure>(TypeErasure& a, TypeErasure& b) {
        a.swap(b);
    }
}

class RandomObjectA {
public:
    void print() const {
        std::cout << "RandomObjectA" << std::endl;
    }
};

class RandomObjectB {
public:
    void print() const {
        std::cout << "RandomObjectB" << std::endl;
    }
};

class RandomObjectC {
public:
    void print() const {
        std::cout << "RandomObjectC" << std::endl;
    }
};

int main() {
    std::vector<TypeErasure> doc;
    doc.push_back(TypeErasure(RandomObjectA()));
    doc.push_back(TypeErasure(RandomObjectB()));
    doc.push_back(TypeErasure(RandomObjectC()));
    std::reverse(doc.begin(), doc.end());
    std::for_each(doc.begin(), doc.end(), [](const TypeErasure& e) {
        e.print();
    });
    return 0;
}