Prev: Performance Factors in C++
Next: How do you exception in your daily C++ programming? - test.cpp (0/1)
From: Anders Dalvander on 6 Sep 2009 16:26 On Sep 5, 1:19 am, "Martin T." <0xCDCDC...(a)gmx.at> wrote: > Is there any way in C++ to automatically generate a memberwise > operator== / operator!= or do you always have to code these operators > yourself? Not automatic, but tuples in boost (and C++1x) makes it easier: #include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple_comparison.hpp> #include <boost/ref.hpp> #include <string> class foo { public: friend bool operator<(const foo& lhs, const foo& rhs) { return boost::make_tuple(boost::cref(lhs.i), boost::cref(lhs.j)) < boost::make_tuple(boost::cref(rhs.i), boost::cref(rhs.j)); } private: std::string i; int j; }; int main() { foo f1; foo f2; return f1 < f2; } Regards, Anders Dalvander -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Martin T. on 6 Sep 2009 20:56 Balog Pal wrote: > "tohava" <tohava(a)gmail.com> >>> I just accept that creating equality operators is part >>> of the coding time and move on. >> I think that part of the problem with this is that whenever a new >> member is added to the class, one must remember to update operator ==. >> Forgetting this can lead to bad behavior. Hence, I do not think this >> is just about saving coding time. > > Now, what is the percentage of classes/structs in a project that has a > meaningful op==? > And then, where it is based on full memberwise comparition? > > Guess if you find the special case, it will not change members all that > often... > > The use case for these structs is representing configuration data. As such there are quite a few of them and I *do* expect them to change quite frequently. For these items memberwise equality is exactly appropriate most of the time. Someone will forget to add to the operator== *especially* if it's only used in the unit tests. The workaround I currently use to safeguard against this is: 1.) operator== is defined in the header 2.) Manually added static assert on the size of the struct inline bool operator==(Cfgdata const& lhs, Cfgdata const& rhs) { #ifdef NDEBUG BOOST_STATIC_ASSERT(sizeof(Cfgdata) == 56); // Check size, so we don't forget to add new members! #endif // ... cheers, Martin -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Ulrich Eckhardt on 6 Sep 2009 20:56 Balog Pal wrote: > "tohava" <tohava(a)gmail.com> >> I think that part of the problem with this is that whenever a new >> member is added to the class, one must remember to update operator ==. >> Forgetting this can lead to bad behavior. Hence, I do not think this >> is just about saving coding time. > > Now, what is the percentage of classes/structs in a project that has a > meaningful op==? > And then, where it is based on full memberwise comparition? There is another problem where C++ doesn't provide a satisfactory solution and that is copying. Actually, that can become a real bummer: struct X { X(X const& rhs): a(rhs.a) {} int a; int b; }; Imagine such a structure being returned from a function. If RVO is in effect, the caller will receive the correct data. If not, the returned object will have its 'b' field uninitialised, but often the memory will earlier have been populated inside the function with a temporary X, so that the value will be just right. Change a few lines or call it in a different context and the fragile thing will fall apart. Been there, done that, wasted lots of time. Uli [x] Introspection for C++ now! -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Balog Pal on 7 Sep 2009 23:11 "Martin T." <0xCDCDCDCD(a)gmx.at> >> Now, what is the percentage of classes/structs in a project that has a >> meaningful op==? >> And then, where it is based on full memberwise comparition? >> >> Guess if you find the special case, it will not change members all that >> often... > > The use case for these structs is representing configuration data. As > such there are quite a few of them and I *do* expect them to change > quite frequently. Sure, I use configs, and indeed members come and go. I still can't recall a case to want op == on the whole config. I read it at some place, possibly write it out as a bulk, and use individual members... but how comparision comes in? > For these items memberwise equality is exactly > appropriate most of the time. It could 'work' indeed but for what situation? (btw I'd guess Boost has tools for such beasts -- tuple, any, ... if plain old struct is not enough) > Someone will forget to add to the operator== *especially* if it's only > used in the unit tests. Well, if it only used in UT, it is a good indication of unwanted ballast that has nothing to do in the real interface. The test should not be that intrusive. And if, for implementation of the harness it needs compare that way -- I really would go with the earlier suggest: code generator. > The workaround I currently use to safeguard against this is: > 1.) operator== is defined in the header > 2.) Manually added static assert on the size of the struct > > inline bool operator==(Cfgdata const& lhs, Cfgdata const& rhs) > { > #ifdef NDEBUG > BOOST_STATIC_ASSERT(sizeof(Cfgdata) == 56); // Check size, so we don't > forget to add new members! > #endif > // ... Interesting idea really. My first line of thought would be 'scrap it'. OTOH I do have situations with similar maintain cases -- the 'offending' functions are mostly I/O routines (like stream op << >> ), and when adding a member I follow the ritual to pick another member and look visit all instances... -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Balog Pal on 7 Sep 2009 23:10 "Ulrich Eckhardt" <eckhardt(a)satorlaser.com> >> Now, what is the percentage of classes/structs in a project that has a >> meaningful op==? >> And then, where it is based on full memberwise comparition? > > There is another problem where C++ doesn't provide a satisfactory solution > and that is copying. Actually, that can become a real bummer: Copy and op= is created to do memberwise stuff since like CFront 2.0? Yeah, getting rid of unwanted ones is not so nice yet (look C++0x for improvements on all fronts...) > struct X { > X(X const& rhs): > a(rhs.a) > {} > int a; > int b; > }; > > Imagine such a structure being returned from a function. This "problem" is a top gotcha for ~ 2 decades. And has an extremely easy solution: do NOT write copyctor, op=. I mean it. Not in user code! Too bad, around the same CFront 2.0 the suggestion went the other way to mitigate some broken *bitwise* copying compilers. With just homegrown stuff in early '90-s it may be even justified, but since we have standard, a deal good libs, and RAII being the norm for ages -- what is really the motivation to write cctor by hand? When you do it, omission is only one of the problems, you drag a full basket of other issues. Slowly "fixing" until the motivator gets out in a base class or member -- then just to discover you could START with using a smart pointer or vector or string instead of a fraking raw pointer... ;-o My experience is to just have two basic cases in user code: forbid cctor and op= or leave the auto-created. Exceptions are in the 'writing library' land, where it is increasingly hard to find a case of a new resource or collection not already covered. > If RVO is in > effect, the caller will receive the correct data. It's plain case of UB. The other usual screw variant is to list all the members -- but forget the base class. That will pick up default init -- likely "work" just do not what ecpected. > Been there, done that, wasted lots of time. And your conclusions on mitigation? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: Performance Factors in C++ Next: How do you exception in your daily C++ programming? - test.cpp (0/1) |