
Edd Dawson wrote:
Here's one I just threw together: http://rafb.net/p/bIQgtl24.html
Sorry, wasn't thinking straight. That link expires after 24 hours. Here we are: #include <boost/scoped_ptr.hpp> #include <sstream> #include <cassert> #include <iostream> template<typename T> class poly_obj { public: template<typename U> explicit poly_obj(const U &obj) : guts_(new guts<U>(obj)) { if (typeid(obj) != typeid(U)) { // static type != dynamic type. // copy-ctor will slice. throw "you've been naughty!"; // ^ std::bad_cast, or related in real life, maybe? } } // this could be templated, if you like poly_obj(const poly_obj &other) : guts_(other.guts_->clone()) { } // so could this poly_obj &operator= (const poly_obj &rhs) { poly_obj temp(rhs); temp.guts_.swap(guts_); return *this; } // These probably won't work if T is const, haven't thought it // through properly const T &get() const { assert(guts_); return guts_->get(); } T &get() { assert(guts_); return guts_->get(); } private: struct guts_base { virtual ~guts_base() { } virtual guts_base *clone() const = 0; virtual T &get() = 0; }; template<typename U> struct guts : guts_base { guts(const U &obj) : obj_(obj) { } guts_base *clone() const { return new guts(obj_); } T &get() { return obj_; } U obj_; }; private: boost::scoped_ptr<guts_base> guts_; }; struct B { virtual ~B() {} }; struct D : B { }; struct E : D { }; int main() { D d; poly_obj<B> po(d); (void)dynamic_cast<D &>(po.get()); std::cout << "We have a D!\n"; E e; try { poly_obj<B>(static_cast<D &>(e)); } catch(const char *bad) { std::cerr << bad << '\n'; } return 0; } Edd