#include <iostream>
#include <vector>
#include <memory>
#include <typeinfo>
class Any {
struct Base {
virtual ~Base () {}
virtual std::ostream & output (std::ostream &) const = 0;
};
template <typename T>
struct Impl : Base {
T value_;
explicit Impl (T x) : value_(x) {}
operator T () const { return value_; }
std::ostream & output (std::ostream &os) const { return os << value_; }
};
std::shared_ptr<const Base> base_ptr_;
public:
Any () : base_ptr_() {}
template <typename T> Any (T x) : base_ptr_(new Impl<T>(x)) {}
template <typename T> operator T () const {
return dynamic_cast<const Impl<T> &>(*base_ptr_.get());
}
friend std::ostream & operator << (std::ostream &os, const Any &a) {
return a.base_ptr_->output(os);
}
};
int main () {
std::vector<Any> v;
// insert heterogeneous data
v.push_back(1);
v.push_back("two");
v.push_back(3.14F);
v.push_back('4');
// demonstrate printing
for (auto i = v.begin(); i != v.end(); ++i) {
std::cout << *i << std::endl;
}
// demonstrate type introspection
for (auto i = v.begin(); i != v.end(); ++i) {
try { static_cast<int>(*i); std::cout << *i << " is int\n"; }
catch (std::bad_cast) {}
try { static_cast<const char *>(*i); std::cout << *i << " is c_str\n"; }
catch (std::bad_cast) {}
try { static_cast<float>(*i); std::cout << *i << " is float\n"; }
catch (std::bad_cast) {}
try { static_cast<char>(*i); std::cout << *i << " is char\n"; }
catch (std::bad_cast) {}
}
}