/*
 * 28th April 2012, Luca Risolia
 */

template<class X>
class Handle {
    X* rep;
    int* pcount;
public:

    X* operator->() {
        return rep;
    }

    Handle(X* pp) : rep(pp), pcount(new int(1)) { }

    template<class Y> operator Handle<Y>() {
        return Handle<Y > (rep);
    };

    Handle(const Handle& r) : rep(r.rep), pcount(r.pcount) {
        (*pcount)++;
    }

    Handle& operator=(const Handle& r) {
        if (rep == r.rep)
            return *this;
        if (--(*pcount) == 0) {
            delete rep;
            delete pcount;
        }
        rep = r.rep;
        pcount = r.pcount;
        (*pcount)++;
        return *this;
    }

    ~Handle() {
        if (--(*pcount) == 0) {
            delete rep;
            delete pcount;
        }
    }
};

class Shape {
};

class Circle : public Shape {
};

int main(int argc, char** argv) {
    Handle<Circle> circle_handle(new Circle());
    Handle<Shape> shape_handle(new Shape());
    shape_handle = circle_handle;
    //circle_handle = shape_handle; // not valid
    return 0;
}
