Programming in D – Solutions

Object

  1. For the equality comparison, rhs being non-null and the members being equal would be sufficient:
    enum Color { blue, green, red }
    
    class Point {
        int x;
        int y;
        Color color;
    
    // ...
    
        override bool opEquals(Object o) const {
            const rhs = cast(const Point)o;
    
            return rhs && (x == rhs.x) && (y == rhs.y);
        }
    }
    
  2. When the type of the right-hand side object is also Point, they are compared according to the values of the x members first and then according to the values of the y members:
    class Point {
        int x;
        int y;
        Color color;
    
    // ...
    
        override int opCmp(Object o) const {
            const rhs = cast(const Point)o;
            enforce(rhs);
    
            return (x != rhs.x
                    ? x - rhs.x
                    : y - rhs.y);
        }
    }
    
  3. Note that it is not possible to cast to type const TriangularArea inside opCmp below. When rhs is const TriangularArea, then its member rhs.points would be const as well. Since the parameter of opCmp is non-const, it would not be possible to pass rhs.points[i] to point.opCmp.
    class TriangularArea {
        Point[3] points;
    
        this(Point one, Point two, Point three) {
            points = [ one, two, three ];
        }
    
        override bool opEquals(Object o) const {
            const rhs = cast(const TriangularArea)o;
            return rhs && (points == rhs.points);
        }
    
        override int opCmp(Object o) const {
            auto rhs = cast(TriangularArea)o;
            enforce(rhs);
    
            foreach (i, point; points) {
                immutable comparison = point.opCmp(rhs.points[i]);
    
                if (comparison != 0) {
                    /* The sort order has already been
                     * determined. Simply return the result. */
                    return comparison;
                }
            }
    
            /* The objects are considered equal because all of
             * their points have been equal. */
            return 0;
        }
    
        override size_t toHash() const {
            /* Since the 'points' member is an array, we can take
             * advantage of the existing toHash algorithm for
             * array types. */
            return typeid(points).getHash(&points);
        }
    }