Search code examples
c++boostbimap

boost::bimap finds wrong entry when using a custom struct as the key, why?


i have a custom struct i am mapping to some data using a boost::bimap. Unfortunately, the bimap find() does not work as expected. Below is a minimal example to demonstrate:

#include <utility>
#include <boost/bimap.hpp>

struct S{
    int a;
    int b;
};
bool operator<(const S& lhs, const S& rhs) {          
    return std::tie(lhs.a, lhs.b) <
            std::tie(lhs.a, lhs.b);
}
bool operator==(const S& lhs, const S& rhs) {
   return 
        lhs.a == rhs.a &&
        lhs.b == rhs.b;
}

int main() {
    boost::bimap<S, int> bmap;

    S s0{0, 0};
    S s1{0, 1};

    bmap.left.insert(std::make_pair(s0, 0));
    bmap.left.insert(std::make_pair(s1, 1));

    auto it0 = bmap.left.find(s0);
    assert(it0 != bmap.left.end());
    auto res0_s = it0->first;
    auto res0 = it0->second;
    assert(res0_s == s0);
    assert(res0 == 0);

    auto it1 = bmap.left.find(s1);
    assert(it1 != bmap.left.end());
    auto res1_s = it1->first;
    auto res1 = it1->second;
    assert(res1_s == s1);
    assert(res1 == 1);
}

The last two asserts are failing (gdb shows that res1_s == s0). I suspect the implementation of operator< is somehow not working as intended. As i understand std::tie, it should just lexicographically compare the two operands and that should suffice to use arbitrary structs as a key for maps.

Thanks for your help.


Solution

  • bool operator<(const S& lhs, const S& rhs) {          
        return std::tie(lhs.a, lhs.b) <
               std::tie(lhs.a, lhs.b);
    }
    

    You've given the same arguments to both calls of std::tie functions, so your operator< always returns false. Change it to following.

    bool operator<(const S& lhs, const S& rhs) {          
        return std::tie(lhs.a, lhs.b) <
               std::tie(rhs.a, rhs.b);
    }