Jump to content
  • Advertisement
Sign in to follow this  
Xentropy

C++ struct has no default memberwise comparison for operator==?!

This topic is 4060 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Everything I've read says structs in C++ should have a default operator== defined automatically that uses memberwise comparison. However, VS2005 doesn't seem to think so. Simple sample code to illustrate issue:
struct testStruct {
	int data1;
	int data2;
	int data3;
};

int main(void) {
	testStruct test;
	testStruct test2;

	if (test == test2) {
		// do something
	}
	
	return 0;
}
Result: error C2676: binary '==' : 'testStruct' does not define this operator or a conversion to a type acceptable to the predefined operator If structs truly shouldn't have a default memberwise operator== implicitly supplied by the compiler, is there a way to define one explicitly that doesn't involve an incredibly long and annoying bit of code (along the lines of if ((member1 == rhs.member1) && (member2 == rhs.member2) && (member3 == rhs.member3) ... )) for a structure with several dozen members? Please tell me there's something very simple I'm missing, because if not, I have a few hundred lines of practically-meaningless code to write for several classes.

Share this post


Link to post
Share on other sites
Advertisement
Well actually I don't work with structs ever so I am not sure if you can do operator overloading there but if it was classes for example you could just overload the == operator for that class.

Share this post


Link to post
Share on other sites
Structs are just classes with default public access instead of default private.

I know I can overload the operator explicitly (as I mentioned), but I have about a dozen classes, each of which uses a data structure with upwards of 50 members. To define an overload of operator== would involve TONS of code. I was hoping for some method that didn't involve typing an entire novel just to implement comparison. Looks like I'm out of luck though. :(

Thanks.

Share this post


Link to post
Share on other sites
http://msdn2.microsoft.com/en-us/library/sah8k6f4(vs.80).aspx

That link suggests this idea:

struct E {
// operator int();
};

int main()
{

E e1, e2;
e1 == e2; // uncomment operator int in class E, then
// it is OK even though neither E::operator==(E) nor
// operator==(E, E) defined. Uses the conversion to int
// and then the builtin-operator==(int, int)
}

Not sure if that helps :-\

Share this post


Link to post
Share on other sites
Quote:
Original post by F1N1TY
http://msdn2.microsoft.com/en-us/library/sah8k6f4(vs.80).aspx

That link suggests this idea:

struct E {
// operator int();
};

int main()
{

E e1, e2;
e1 == e2; // uncomment operator int in class E, then
// it is OK even though neither E::operator==(E) nor
// operator==(E, E) defined. Uses the conversion to int
// and then the builtin-operator==(int, int)
}

Not sure if that helps :-\


Nope as this can only work in situations where there is only one member, in which case writing a real operator= is trivial.

Never use implicit operator functions.You will find that the compiler starts being very free with where it does such conversions, not always where you expect.

Share this post


Link to post
Share on other sites
Quote:
Original post by Xentropy
I have about a dozen classes, each of which uses a data structure with upwards of 50 members.


Jebus, what the hell are you doing to involve such unwieldy structures requiring comparison semantics?

Share this post


Link to post
Share on other sites
Well, if that doesn't help, this conversation from GDNet IRC will:

<F1N1TY> you guys know anything about this: (Link to this forum)
<Zao> F1N1TY: Afair, there's no default op==
<Zao> Only the ctor, cctor, op= and dtor are automagic.

Share this post


Link to post
Share on other sites
Sadly, that isn't too helpful since it doesn't even show how E::int() is defined, just the declaration. And a structure that's several kilobytes long isn't going to fit in any built-in type, so I don't see how casting the structures is going to help me.

Thanks for trying, though. :)

Just for more background if anyone wonders why I have such large structures, I'm reading records from a database file, and some of the records are quite large. To compare one record to another to find out if it's equal requires every member of the structures be compared. It seems to me like such a simple method of comparison would be implicitly assumed. It may not always be correct, but it'd at least mean only overloading operator== in those cases instead of every case. I'm comparing actual data, not pointers or references, so memberwise comparison would work fine. (I'm storing strings in std::strings so == is defined for those too.)

Share this post


Link to post
Share on other sites
Normally you'd compare row keys, not row data.

Assuming I actually needed a data-comparison function (YAGNI!!!), there's a couple of options.

1) If you want your structures to be "POD", evil #define magic involving BOOST_PP_*.

2) If not-quite-"POD" is okay, having the subcomponents of a row structure automatically register themselves in a table of some sort that allows iteration over the elements both for loading database entries or performing operations on them instead of hardcoding everything about each row every time. Possibly using BOOST_PP_* magic again, but it's avoidable here.

3) Not-at-all-"POD", instead pretending C++ is a dynamic language by making row elements an array of boost::variant< std::string, int, ... > or similar (with view accessors for easy access and improved type checking if desired).

Share this post


Link to post
Share on other sites
If your structs are POD types (Plain Old Data), then you can safely and portably (is that even a word? [smile]) do a memcpy in your operator==(). If you're feeling really game you may be able to get away with doing this for non-POD types as well, but whether this will work or not depends on the types involved and your compiler.....and it is in no way portable.


struct testStruct {
int data1;
int data2;
int data3;

testStruct& operator=(const testStruct& rhs) {
memcpy(reinterpret_cast<char*>(this),
reinterpret_cast<const char*>(&rhs),
sizeof(testStruct));
}
};

int main(void) {
testStruct test;
testStruct test2;

if (test == test2) {
// do something
}

return 0;
}



EDIT: Umm.....I have no idea why I was thinking operator=() but typing operator==(). Replace memcpy with memcmp and the same hold though [rolleyes]

[Edited by - joanusdmentia on June 8, 2007 7:21:29 AM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!