-1

i have little problem with c++ std::map container and structure as key.

I want to use map as fast lookup table for ipv6 lookup table. I have file with ip addresses and i want aggregate them.

my key for map is

struct myipv6{
uint64_t MSB;
uint64_t LSB;

bool operator==(const myipv6 &a){
            return (MSB == a.MSB && LSB == a.LSB);
}

bool operator<(const myipv6 &a){
                return (MSB < a.MSB && LSB < a.LSB);
}
myipv6(){}
myipv6(const uint64_t A,const uint64_t B) :
    MSB(A),LSB(B) {}
};

bool operator < (const myipv6 &l, const myipv6 &r) { return ( l.MSB < r.MSB && l.LSB < r.LSB); }

Data is inserted from in6_addr by

memcpy(&(ip), &src_addr, sizeof(myipv6));

this construction work, i tried copy data to ip. From ip use memcpy to another in6_addr and used inet_pton to check if values are correct.

map is declared as

map<myipv6, int> aggregate;
map<myipv6, int>::iterator it;

when i go through all ip address in file and use this for aggregation:

    it = aggregate.find(ip);
    if(!(ip == it->second.ip)){
            aggregate[ip] = 1;
    }else{
            it->second += 1;
    }

i get bad result, records is lost ... when i use it == aggregate.end() instead of !(ip == it->second.ip) for condition in else statement i get that it->first is not equal with ip. But when i use !(ip == it->second.ip) iterator has any value and when i write "new" item to map i rewrite saved data.

Any thoughs for this strange behavior ?

One last question, is it possible to use unordered_map instead of map ?

Thanks

Tomas Lysek
  • 143
  • 2
  • 10

1 Answers1

3

You should use:

bool operator < (const myipv6 &l, const myipv6 &r) {
    return (l.MSB < r.MSB) || (l.MSB == r.MSB && l.LSB < r.LSB);
}

This is called lexicographical order.

The whole class could look like that:

struct myipv6 {
    uint64_t MSB;
    uint64_t LSB;

    friend bool operator==(const myipv6 &a, const myipv6 &b) {
            return (a.MSB == b.MSB && a.LSB == b.LSB);
    }

    friend bool operator<(const myipv6 &a, const myipv6 &b) {
                return (a.MSB < b.MSB) || (a.MSB == b.MSB && a.LSB < b.LSB);
    }

    myipv6() {}

    myipv6(const uint64_t A,const uint64_t B) : MSB(A),LSB(B) {}
};

Using friend is an elegant way to define theses comparison operators.

Danvil
  • 22,240
  • 19
  • 65
  • 88
  • 5
    @TomasLysek In C++11, there is an easy way to implement comparison operators using [`std::tie`](http://en.cppreference.com/w/cpp/utility/tuple/tie). Once you have more than two data members doing it by hand becomes painful and error prone. – juanchopanza Apr 06 '14 at 08:47
  • @TomasLysek That one is nice –  Apr 06 '14 at 08:50