------- 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

Reply via email to