------- Comment #3 from varg at theor dot jinr dot ru 2008-03-13 11:17 ------- Even more simple program:
template <class T> class ptr { T* p; public: ptr(T* t) throw() : p(t) { p->set_refcount(1); } explicit ptr(T& t) throw() : p(&t) { p->add_reference(); } ptr(const ptr& other) throw() : p(other.p) { p->add_reference(); } ~ptr() { if (p->remove_reference() == 0) delete p; } ptr& operator=(const ptr& other) { T* otherp = other.p; otherp->add_reference(); if (p->remove_reference() == 0) delete p; p = otherp; return *this; } T& operator*() const throw() { return *p; } T* operator->() const throw() { return p; } }; class refcounted { public: refcounted() throw() : refcount(0) { } unsigned add_reference() throw() { return ++refcount; } unsigned remove_reference() throw() { return --refcount; } unsigned get_refcount() const throw() { return refcount; } void set_refcount(unsigned r) throw() { refcount = r; } private: unsigned refcount; }; class ex; class basic : public refcounted { public: basic() : flags(false) { } basic(const basic& other) : flags(false) { } virtual basic* duplicate() const { return new basic(*this); } virtual ex eval() const; virtual ~basic() { } protected: mutable bool flags; private: friend class ex; }; class ex { private: mutable ptr<basic> bp; static ptr<basic> construct_from_basic(const basic& other) { if (other.flags) return ptr<basic>(const_cast<basic &>(other)); else { basic* t = other.duplicate(); t->flags = true; return t; } } public: ex(const basic& other) : bp(construct_from_basic(other)) { } ex eval() const { return bp->eval(); } }; ex basic::eval() const { return *this; } class oops : public basic { public: oops() { } oops* duplicate() const { return new oops(*this); } ex eval() const { return oops(); } }; int main(int argc, char** argv) { const ex e = oops(); const ex& f = argc > 1 ? e : e.eval(); const ex& g = f.eval(); return 0; } -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35548