This comes from a small thread that is going on in digitalmars.D.learn.
This program asserts:
import std.c.string;
struct S { // 16 bytes, with a hole
ushort s;
double d;
}
void main() {
S s1, s2;
memset(&s1, ubyte.min, S.sizeof);
memset(&s2, ubyte.max, S.sizeof);
s1.s = s2.s = 0;
s1.d = s2.d = 0;
assert(s1 == s2);
}
But a correctly implemented opEquals (and opCmp) among structs has to ignore
the contents of the holes, because they can be filled with anything, for
example if the structs where not initialized (with =void).
A correct opEquals has to work recursively (so if the struct contains a string,
it has to control the string equality too).
And a built-in recursive opCmp/opHash for structs is about as useful as having
a correct opEquals.
A correct opEquals can be a little slower, but correctness come first. In the
uncommon situations where I really need max speed and I don't care of
correctness I can use a memcmp(&s1, &s2, S.sizeof). (And the compiler is free
to use just memcmp when a struct has no holes and doesn't contain references,
associative arrays and dynamic arrays).
Correctness of basic struct operators is not an optional feature, like
properties or even enums. If the opEquals among structs is wrong then it's
better to not have it at all.
Bye,
bearophile