Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a "future-safe" compare operator be crafted in C++?

Greetings all,

Is it possible to craft a future-safe comparison operator (==) in C++?

The problem I faced was that we have a class with multiple members. We have a comparison operator to validate if instance-1 of the object has the same values as instance-2.

i.e. we can do

class blarg {
    .....
};

.....

blarg   b1(..initializers...);
blarg   b2 = b1;

if (b1 == b2) {
    ... then do something ....
}

However, I had a co-worker that added a new member to the class, but failed to update the comparison operator. This lead to problems that took a while for us to figure out.

Is there a coding practice, I mean other than code review (that failed for us), or coding method, design, template, magic beans, whatever that could help avoid situations like this?

My first reaction was to use the memcmp command. However, after reading the stack overflow entry for "Comparing structures in C vs C++" I see that this can be problematic due to C++ classes having more than just the member data inside.

How do others deal with this?

Thank you in advance for your help.

like image 551
John Rocha Avatar asked Dec 22 '10 17:12

John Rocha


1 Answers

Well, the obvious solution is to be more careful when you extend the original class. :) "Being more careful" includes things like code reviews, things like that, but obviously this isn't fool proof.

So tackling this problem from a philosophical point of view, rather than a technical one, can often provide insight. The philosophy in this case is that of being a paranoid programmer. Assume that code you write today will be broken by some nitwit months or years from now. (Edit per @Noah's comments below: More often than not, that nitwit is myself. Being a paranoid programmer protects me from myself probably more than anyone else.) If you can do something to ensure that when the nitwit does break your code something fails before the product is shipped, that would help.

Two things I like to use are static assertions and unit tests. A static assertion can be used in your operator== code to verify that the sizeof your class is what you expect it to be. For example:

bool MyClass::operator==(const MyClass& rhs) const
{
  static_assert(sizeof(MyClass) == sizeof(foo_) + sizeof(bar_))
  ...
}

...where foo_ and bar_ are member variables. This will break the compile when the size of the class has changed.

As static assertion usually takes the form of a template class that will fail to compile when the expression is false. This can be a little tricky to write (but it's an interesting exercise -- consider what happens if you try to add a char test_[0] member to a class). Fortunately, this wheel has already been invented. See Boost for an example, and I think the new MSVC compiler comes with one as well.

like image 107
John Dibling Avatar answered Oct 26 '22 12:10

John Dibling