Boost logo

Boost :

From: Edd Dawson (lists_at_[hidden])
Date: 2007-09-03 16:44:08


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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk