// file : Utility/Hetero/Container.hpp // author : Boris Kolpackov // copyright : Copyright (c) 2002-2003 Boris Kolpackov // license : http://kolpackov.net/license.html #ifndef UTILITY_HETERO_CONTAINER_HPP #define UTILITY_HETERO_CONTAINER_HPP #include namespace Utility { namespace Hetero { // // // class Typing {}; // // // class Container { public: ~Container () { delete holder_; } public: template Container (T const& t) : holder_ (new TypedHolder (t)) { } Container (Container const& c) : holder_ (c.holder_->clone ()) { } public: template Container& operator= (T const& t) { delete holder_; holder_ = 0; holder_ = new TypedHolder (t); return *this; } Container& operator= (Container const& c) { delete holder_; holder_ = 0; holder_ = c.holder_->clone (); return *this; } public: template operator T& () { return value (); } template operator T const& () const { return value (); } public: template T& value () { if (holder_->type () == typeid (T)) { return dynamic_cast*>(holder_)->value (); } else { throw Typing (); } } template T const& value () const { if (holder_->type () == typeid (T)) { return dynamic_cast*>(holder_)->value (); } else { throw Typing (); } } public: std::type_info const& type () const { return holder_->type (); } public: template friend T operator+ (Container const& a, T const& b) { return a.value () + b; } template friend T operator+ (T const& a, Container const& b) { return a + b.value (); } private: struct Holder { virtual ~Holder () {} virtual Holder* clone () const = 0; virtual std::type_info const& type () const = 0; }; template struct TypedHolder : public Holder { TypedHolder (T const& value) : value_ (value) { } virtual Holder* clone () const { return new TypedHolder (value_); } virtual std::type_info const& type () const { return typeid (T); } T const& value () const { return value_; } T& value () { return value_; } private: T value_; }; Holder* holder_; }; } } #endif // UTILITY_HETERO_CONTAINER_HPP //$Id$