Prev: constructor declaration ended with comma - is this a valid C++ syntax
Next: Exception Specification Compromise
From: dragoncoder on 2 Feb 2010 06:12 Hi all, I have the following code. // db_operators.h #ifndef INCLUDED_DB_OPERATORS #define INCLUDED_DB_OPERATORS #include <cstring> struct ecodb2{ unsigned long long id; char code[21]; }; inline bool operator==(const ecodb2& lhs, const ecodb2& rhs) { std::cout << "Some text" << std::endl; return ((lhs.id == rhs.id) || !std::strcmp(lhs.code, rhs.code)); } struct Compare { bool operator()(const ecodb2& lhs, const ecodb2& rhs) const { bool retval = false; if(lhs.id < rhs.id) retval = true; else if(lhs.id == rhs.id) retval = std::strcmp(lhs.code, rhs.code); return retval; } }; #endif // main.cpp #include <iostream> #include <cstring> #include <set> #include <db_operators.h> int main() { std::set<ecodb2, Compare> industry_codes; ecodb2 val; val.id = 1; std::strncpy(val.code, "GOV", sizeof(val.code)); industry_codes.insert(val); std::strncpy(val.code, "ABC", sizeof(val.code)); std::set<ecodb2>::iterator it = industry_codes.find(val); if(it != industry_codes.end()) std::cout << "Found in set" << std::endl; else std::cout << "Not found in set" << std::endl; } While running this code, I expect to see Found in set (as either id or code match meaning a perfect match) and also "Some text" being printed, becasue set::find should call my custom operator==() function to find a match but the output I get is "Not found in set" and also "Some text" is not getting printed. Please help. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Bart van Ingen Schenau on 2 Feb 2010 21:46 On Feb 3, 12:12 am, dragoncoder <pktiw...(a)gmail.com> wrote: > Hi all, I have the following code. > > // db_operators.h > > #ifndef INCLUDED_DB_OPERATORS > #define INCLUDED_DB_OPERATORS > > #include <cstring> > > struct ecodb2{ > unsigned long long id; > char code[21]; > > }; > > inline bool operator==(const ecodb2& lhs, > const ecodb2& rhs) > { > std::cout << "Some text" << std::endl; > return ((lhs.id == rhs.id) || !std::strcmp(lhs.code, rhs.code)); > > } > > struct Compare > { > bool operator()(const ecodb2& lhs, > const ecodb2& rhs) const > { > bool retval = false; > if(lhs.id < rhs.id) > retval = true; > else if(lhs.id == rhs.id) > retval = std::strcmp(lhs.code, rhs.code); > return retval; > } > > }; > > #endif > > // main.cpp > > #include <iostream> > #include <cstring> > #include <set> > > #include <db_operators.h> > > int main() > { > std::set<ecodb2, Compare> industry_codes; > > ecodb2 val; > val.id = 1; > > std::strncpy(val.code, "GOV", sizeof(val.code)); > industry_codes.insert(val); > > std::strncpy(val.code, "ABC", sizeof(val.code)); > > std::set<ecodb2>::iterator it = industry_codes.find(val); > if(it != industry_codes.end()) > std::cout << "Found in set" << std::endl; > else > std::cout << "Not found in set" << std::endl; > > } > > While running this code, I expect to see Found in set (as either id or > code match meaning a perfect match) and also "Some text" being > printed, becasue set::find should call my custom operator==() function > to find a match but the output I get is "Not found in set" and also > "Some text" is not getting printed. Your custom operator==() will never be called, because all std::set (and std::map) operations are defined in terms of the Compare object that you provide (or operator< if you don't specify it). Equality (or rather, equivalence) of two set elements A and B is defined as ( not Compare(A,B) && not Compare(B, A) ) or in terms of ordering: neither comes before the other. > > Please help. > Bart v Ingen Schenau -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: tohava on 2 Feb 2010 21:49 On Feb 3, 1:12 am, dragoncoder <pktiw...(a)gmail.com> wrote: > Hi all, I have the following code. > > // db_operators.h > > #ifndef INCLUDED_DB_OPERATORS > #define INCLUDED_DB_OPERATORS > > #include <cstring> > > struct ecodb2{ > unsigned long long id; > char code[21]; > > }; > > inline bool operator==(const ecodb2& lhs, > const ecodb2& rhs) > { > std::cout << "Some text" << std::endl; > return ((lhs.id == rhs.id) || !std::strcmp(lhs.code, rhs.code)); > > } > > struct Compare > { > bool operator()(const ecodb2& lhs, > const ecodb2& rhs) const > { > bool retval = false; > if(lhs.id < rhs.id) > retval = true; > else if(lhs.id == rhs.id) > retval = std::strcmp(lhs.code, rhs.code); > return retval; > } > > }; > > #endif > > // main.cpp > > #include <iostream> > #include <cstring> > #include <set> > > #include <db_operators.h> > > int main() > { > std::set<ecodb2, Compare> industry_codes; > > ecodb2 val; > val.id = 1; > > std::strncpy(val.code, "GOV", sizeof(val.code)); > industry_codes.insert(val); > > std::strncpy(val.code, "ABC", sizeof(val.code)); > > std::set<ecodb2>::iterator it = industry_codes.find(val); > if(it != industry_codes.end()) > std::cout << "Found in set" << std::endl; > else > std::cout << "Not found in set" << std::endl; > > } > > While running this code, I expect to see Found in set (as either id or > code match meaning a perfect match) and also "Some text" being > printed, becasue set::find should call my custom operator==() function > to find a match but the output I get is "Not found in set" and also > "Some text" is not getting printed. I don't think it should be possible for 2 variables of type ecodb2 to be satisfy both x < y and x == y. This can happen with your code (in the case where x and y share an id but not a code). My guess would be that find checks at some point for some x and y whether x < y, and if this is the case, it assumes that x != y, which in your example is NOT the case. I would recommend implementing this using two maps, one with id as key, and one with code. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran on 2 Feb 2010 21:47 On Feb 3, 12:12 am, dragoncoder <pktiw...(a)gmail.com> wrote: > Hi all, I have the following code. > > // db_operators.h > > #ifndef INCLUDED_DB_OPERATORS > #define INCLUDED_DB_OPERATORS > > #include <cstring> > > struct ecodb2{ > unsigned long long id; > char code[21]; > > }; > > inline bool operator==(const ecodb2& lhs, > const ecodb2& rhs) > { > std::cout << "Some text" << std::endl; > return ((lhs.id == rhs.id) || !std::strcmp(lhs.code, rhs.code)); > > } > > struct Compare > { > bool operator()(const ecodb2& lhs, > const ecodb2& rhs) const > { > bool retval = false; > if(lhs.id < rhs.id) > retval = true; > else if(lhs.id == rhs.id) > retval = std::strcmp(lhs.code, rhs.code); > return retval; > } > > }; > > #endif > > // main.cpp > > #include <iostream> > #include <cstring> > #include <set> > > #include <db_operators.h> > > int main() > { > std::set<ecodb2, Compare> industry_codes; > > ecodb2 val; > val.id = 1; > > std::strncpy(val.code, "GOV", sizeof(val.code)); > industry_codes.insert(val); > > std::strncpy(val.code, "ABC", sizeof(val.code)); > > std::set<ecodb2>::iterator it = industry_codes.find(val); > if(it != industry_codes.end()) > std::cout << "Found in set" << std::endl; > else > std::cout << "Not found in set" << std::endl; > > } > > While running this code, I expect to see Found in set (as either id or > code match meaning a perfect match) and also "Some text" being > printed, becasue set::find should call my custom operator==() function > to find a match but the output I get is "Not found in set" and also > "Some text" is not getting printed. Well, first things first: you should have gotten a warning (and you should not have ignored it) on line that says retval = std::strcmp(lhs.code, rhs.code); That line makes your set ordering wrong. I guess it all goes downhill form there. To get correct ordering, use: retval = std::strcmp(lhs.code, rhs.code)<0; Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Paul Bibbings on 3 Feb 2010 00:31 dragoncoder <pktiwary(a)gmail.com> writes: > Hi all, I have the following code. > > // db_operators.h > > #ifndef INCLUDED_DB_OPERATORS > #define INCLUDED_DB_OPERATORS > > #include <cstring> > > struct ecodb2{ > unsigned long long id; > char code[21]; > }; > > inline bool operator==(const ecodb2& lhs, > const ecodb2& rhs) > { > std::cout << "Some text" << std::endl; > return ((lhs.id == rhs.id) || !std::strcmp(lhs.code, rhs.code)); > } > > struct Compare > { > bool operator()(const ecodb2& lhs, > const ecodb2& rhs) const > { > bool retval = false; > if(lhs.id < rhs.id) > retval = true; > else if(lhs.id == rhs.id) > retval = std::strcmp(lhs.code, rhs.code); > return retval; > } > }; > > #endif > > // main.cpp > > #include <iostream> > #include <cstring> > #include <set> > > #include <db_operators.h> > > int main() > { > std::set<ecodb2, Compare> industry_codes; ^^^^^ <snip></snip> > } > > While running this code, I expect to see Found in set (as either id or > code match meaning a perfect match) and also "Some text" being > printed, becasue set::find should call my custom operator==() function > to find a match but the output I get is "Not found in set" and also > "Some text" is not getting printed. > > Please help. I do not believe that std::set makes comparisons in the way you expect, though I am not near my copy of the standard to check out the exact details. Were you not to provide the second template parameter `Compare', as you do above, then this would default to std::less. I would suspect that set::find uses the same method as is used also for ordering of items in the set, probably - where the default is used - applying some such model of equality as: !(rhs < lhs && lhs < rhs) using std::less. Thus, when leaving set to use the default comparator, std::less, you would take control by implementing op< and not op==. However, in providing your Compare class you are effectively saying that you want this to play the role that std::less would have played otherwise, effectively translating equality in this instance to something like: !(aCompare(rhs, lhs) && aCompare(lhs, rhs)) Either way, and whatever the details are, it seems clear that set::find is not using op== to test equality, and so your custom op== is not not found because it is not a good match - it is not even looking for it. Step through your code in a debugger and I am sure you will see that set::find is using Compare::op() to handle equality testing. What is more, take out the second template argument to the declaration of your set, so that this becomes: std::set<ecodb2> industry_codes; and I think that you will find that you compiler complains about a missing op<, not op==. Try either something along the lines of this model: #include <iostream> #include <set> struct A { A(int i): i_(i) { } int i_; }; bool operator<(const A& lhs, const A& rhs) { return lhs.i_ < rhs.i_; } int main() { std::set<A> my_set; my_set.insert(3); my_set.insert(7); my_set.insert(1); std::set<A>::const_iterator i = my_set.find(A(3)); if (i != my_set.end()) std::cout << "Gotcha!\n"; else std::cout << "Hhm...\n"; return 0; } or else replace op< with: struct Compare { bool operator()(const A& lhs, const A& rhs) { return lhs.i_ < rhs.i_; } }; and use: std::set<A, Compare> my_set; which is closer to your original attempt. I hope this helps, and is even vaguely correct. Regards Paul Bibbings -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 Prev: constructor declaration ended with comma - is this a valid C++ syntax Next: Exception Specification Compromise |