std::map key

struct Struct_Key
{
        uint32_t _my_type;
        uint32_t _my_flag;
        uint32_t _my_val;
        uint32_t _my_val_my_type;

        Struct_Key(uint32_t type, uint32_t flag, uint32_t val, uint32_t val_type) :
                _my_type(type), _my_flag(flag), _my_val(val),
               _my_val_my_type(val_type) {}

        bool operator<(const Struct_Key& t) const
        {
                return (_my_type < t._my_type) ||
                 (_my_type == t._my_type && _my_flag < t._my_flag) ||
                 (_my_type == t._my_type && _my_flag == t._my_flag && _my_val < t._my_val) ||
                 (_my_type == t._my_type && _my_flag == t._my_flag && _my_val == t._my_val && _my_val_my_type <= t._my_val_my_type);
        }

        //bool operator<(const Struct_Key& n2) const {
        //      return !(_my_type < n2._my_type || _my_flag < n2._my_flag || _my_val < n2._my_val || _my_val_my_type < n2._my_val_my_type);
        //}
};

int main(int argc, char *argv[]){
        std::map<Struct_Key, uint32_t> my_map;
        std::map<Struct_Key, uint32_t>::iterator my_map_iterator;

        Struct_Key key(1, 2, 3, 4);
        my_map_iterator = my_map.find(key);
        if ( my_map_iterator == my_map.end()) {
                my_map.insert(std::make_pair(key, 0));
                printf ("Key not found\n");
        } else {
                printf ("Key Exists");
        }

        Struct_Key key_1(1, 2, 3, 4);
        my_map_iterator = my_map.find(key_1);
        if ( my_map_iterator == my_map.end()) {
                my_map.insert(std::make_pair(key_1, 1));
                printf ("Key not found\n");
        } else {
                printf ("Key Exists");
        }

}

Open in new window


The output I get is
Key not found
Key not found

I was expecting
Key not found
Key Exists.
perlperlAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

perlperlAuthor Commented:
Anything to do with struct padding?
0
perlperlAuthor Commented:
I gave up on regular operator <. I have no idea why it didn't work.

I am using Boost instead and it works

#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>

        return (boost::tie(boost::cref(_my_type) , boost::cref(_my_flag), boost::cref(_my_val), boost::cref(_my_val_my_type)) <
                boost::tie(boost::cref(t._my_type), boost::cref(t._my_flag), boost::cref(t._my_val), boost::cref(t._my_val_my_type) ));
0
chaauCommented:
In order for the Find() method to work you need to specify operator==() for the Struct_key
0
Become a CompTIA Certified Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

perlperlAuthor Commented:
I had that suspicion in my earlier post ;)

http://www.experts-exchange.com/Programming/Languages/CPP/Q_28241102.html#a39500027

http://www.experts-exchange.com/Programming/Languages/CPP/Q_28241102.html#a39500036

I am confused but Well, after using boost it is working without ==
I am only overloading '<' and its working for both insert and find

bool operator<(const Struct_Key& t) const
{
  return (boost::tie(boost::cref(_my_type) , boost::cref(_my_flag), boost::cref(_my_val), boost::cref(_my_val_my_type)) <
                boost::tie(boost::cref(t._my_type), boost::cref(t._my_flag), boost::cref(t._my_val), boost::cref(t._my_val_my_type) ));
}
0
perlperlAuthor Commented:
/******** THIS does not work ****/
bool operator<(const Struct_Key& n2) const {
             return !(_my_type < n2._my_type || _my_flag < n2._my_flag ||
 _my_val < n2._my_val || _my_val_my_type < n2._my_val_my_type);
        }

bool operator==(const Struct_Key& n2) const {
              return (_my_type == n2._my_type && _my_flag == n2._my_flag
 && _my_val == n2._my_val && _my_val_my_type == n2._my_val_my_type);
        }

/************ THIS WORKS ********/
bool operator<(const Struct_Key& t) const 
{
  return (boost::tie(boost::cref(_my_type) , boost::cref(_my_flag), boost::cref(_my_val), boost::cref(_my_val_my_type)) <
                boost::tie(boost::cref(t._my_type), boost::cref(t._my_flag), boost::cref(t._my_val), boost::cref(t._my_val_my_type) ));
}

Open in new window

0
chaauCommented:
Have you tried to debug? What happens if you put a breakpoint in the operator <? When you call find() you are expected to hit the breakpoint twice (once for the key that is already in the map, and once for the new key). Both times it is supposed to return false. Ignore my comment regarding operator ==, the find() function uses operator< twice. I expect both Sarah's and my solution should return false
0
evilrixSenior Software Engineer (Avast)Commented:
Your object does not need to implement an equality operator, it only needs a less than operator. Equality is tested thus:

!(a<b)&&!(b<a)

In other words if a is not less than b and b is not less than a they are equal.

There is probably a problem with your less than predicate. On a train atm but will check later.
0
evilrixSenior Software Engineer (Avast)Commented:
The last clause in your predicate uses <= on the final check, so it means your predicate is actually a less than or equal comparitor. Try changing it to be just less than.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ZoppoCommented:
Hi,

in the original posted code IMO a problem is the <= in the last expression in the operator < here: _my_val_my_type <= t._my_val_my_type. This can lead to weak ordering (see http://en.wikipedia.org/wiki/Strict_weak_ordering) because this may return TRUE even in case both structs are equal. The latter versions where you removed comparsion of equalness are even worse. Both cases can lead to situations where the a < b != b > a, this I guess leads to the problem.

Hope that helps,

ZOPPO
0
ZoppoCommented:
Sorry, evilrix - you were too fast :)

@perlperl: please ignore my comment if evilrix guess (and so mine too) is right ...
0
evilrixSenior Software Engineer (Avast)Commented:
No problem amigo - your comments add some very useful information for the asker :)
0
perlperlAuthor Commented:
Hmmm nice catch ;)
I will try later...in my bed now ;)

I blindly copy pasted 'sarabande' code from earlier post. Well, now i learnt how to use boost which is much shorter ;)
0
evilrixSenior Software Engineer (Avast)Commented:
>> Well, now i learnt how to use boost
Most definitely a good thing.

One other small observation (not sure if this was originally from Sara's code)... try not to use leading underscore for symbol names. There are a number of situations in the standard where these names are reserved for the implementation (the compiler's use) and whilst it doesn't out right ban them and there are exceptions where it is safe it is generally better to just avoid using this.

I prefer to use training underscore and, specifically, use this when I am naming private class members, which is the same paradigm adopted by Boost.
0
sarabandeCommented:
yes, it was my mistake in the previous question. the operator< must not use a <= at end or x < y and y < x would not both evaluate to false when x is equal to y.

Sara
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.