|
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