2

I'm trying to do something like this:

class foo {
    virtual void bool operator==(foo const & rhs) = 0;
};

class bar1 : public foo {
    bool operator==(bar1 const & rhs) { ... }
};

class bar2 : public foo {
    bool operator==(bar2 const & rhs) { ... }
};

That is, I want to indicate that all classes implementing the foo interface must implement the operator== method for its own derived class.

But, the compiler is complaining that bar1 and bar2 are still abstract classes because they haven't implemented operator==(foo const &) yet.

I've considered changing the function signature to foo const & in both bar1 and bar2 then doing dynamic_cast inside the function, but that seems messy:

class bar1 : public foo {
    bool operator==(foo const & rhs) {
        const bar1 * casted_rhs = dynamic_cast<const bar1 *>(&rhs);
        if (casted_rhs == NULL) {
            // not a bar1
            return false;
        } else {
            // go through rhs and this object and find out if they're equal
        }
    }
}

This feels messy.

There must be a better way to do this.

achow
  • 1,013
  • 2
  • 12
  • 20

2 Answers2

5

You can use a CRTP pattern in order to force this situation. With this way, template base class force to implement operator== in derived classes:

template <typename T>
class foo {
    bool operator==(const T & rhs)
    {
        return static_cast<T>(*this).operator==(static_cast<T>(rhs));
    }
};

class bar1 : public foo<bar1> {
    bool operator==(const bar1  & rhs)
    {
    }
};

class bar2 : public foo<bar2> {
    bool operator==(const bar2 & rhs)
    {

    }
};
Community
  • 1
  • 1
Tio Pepe
  • 3,071
  • 1
  • 17
  • 22
  • I don't think static inheritance is suitable for this - there are quite a few downsides such as `bar1` and `bar2` being derived from different classes. – Pubby Nov 07 '11 at 07:26
  • Would this be the generally-accepted way of forcing what I want to do in C++ ? – achow Nov 07 '11 at 07:36
  • Take a look in [Wikipedia](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). There is a good explanation. – Tio Pepe Nov 07 '11 at 07:45
  • you got a typo, should be '==' not single '=' – AndersK Nov 07 '11 at 07:47
  • @AndersK. Yes, I know. Thanks, it's for explanation purposes. I readed the comments above. – Tio Pepe Nov 07 '11 at 07:51
  • It seems that I've now lost the ability to use `foo` as an interface. That is, I'm no longer able to pass around `foo *` pointers, and am forced to declare the pointers as `foo *` or `foo *`. What am I doing wrong? – achow Nov 07 '11 at 07:57
  • @highwind777: Nothing. That's what Pubby meant by his initial comment. This isn't a particularly useful place for inheritance, since if you're working on pointers to the base class, you can't use the equality operator anyhow [as it expects concrete instances of the child class]. – Dennis Zickefoose Nov 07 '11 at 08:17
1

That is because you are not overriding those exact methods.

class bar1 : public foo {
    bool operator==(bar1 const & rhs) { ... }
};

class bar2 : public foo {
    bool operator==(bar2 const & rhs) { ... }
};

should be changed to

class bar1 : public foo {
    bool operator==(foo const & rhs) { ... }
};

class bar2 : public foo {
    bool operator==(foo const & rhs) { ... }
};

and you are good to go. You should read more about polymorphism

Mykolas Simutis
  • 212
  • 1
  • 10
  • But this is not a good idea: imagine something like `bar1 = bar2`. With your solution, this compile but is not the right solution. – Tio Pepe Nov 07 '11 at 07:26
  • Yes, but there are situations where bar1 = bar2 is the right way. Also, it can be taken care by having an enum of object types and return false if they do not match, but in that case I guess your solution is more elegant and more "c++ way". – Mykolas Simutis Nov 07 '11 at 07:32
  • This is what I have written in my question. I said I'm tempted to change the function signature to `operator==(foo const &)` and then do `dynamic_cast` inside the code to ensure the type matches. I'm looking for a better solution. – achow Nov 07 '11 at 07:32
  • Assuming you're talking about 'bool operator==' then this solution seems like the right one to me. I don't see anything wrong with checking for equality polymorphically. As an aside, the equality operators could be 'const' mehtods. – juanchopanza Nov 07 '11 at 07:42
  • @juanchopanza I'm trying to avoid using `dynamic_cast` – achow Nov 07 '11 at 07:55
  • @highwind7777 You're right to avoid it, and I don't think you need it at all, as long as whatever you need to establish equality is available via foo's public interface. – juanchopanza Nov 07 '11 at 09:36