Home > Software engineering >  std::map with custom key
std::map with custom key

Time:05-31

I would like to use a standard map with the following custom key:

struct ParserKey{
    ParserKey(uint16_t compno,
             uint8_t resno,
             uint64_t precinctIndex) : compno_(compno),
                                       resno_(resno),
                                       precinctIndex_(precinctIndex)
    {
    }
     uint16_t compno_;
     uint8_t resno_;
     uint64_t precinctIndex_;
};

There's no obvious way of ordering the keys, though. Can these keys be ordered, or do I need a different associative collection ?

CodePudding user response:

If you don't care about the specific order and just want to satisfy the requirements for sorting, a common and simple pattern is to use std::tie with all of the class members of the compared instances, and compare those results instead.

std::tie creates a std::tuple of references to the members, and std::tuple implements operator< which compares its elements (the members of the object in this case) lexicographically.

In your case, using member operator< :

bool operator<(const ParserKey & other) const
{
    return std::tie(compno_, resno_, precinctIndex_) < 
        std::tie(other.compno_, other.resno_, other.precinctIndex_);
}

Live example https://godbolt.org/z/v433v54jz

CodePudding user response:

You can just impose any arbitrary total order on these integers in the same style as std::lexicographical_compare does.

So, the lazy approach is:

// inside ParserKey ...

std::array<std::uint16_t,3> to_array() const {
  return {compno_, resno_, precinctIndex_};
}

friend bool operator<(ParserKey const& lhs, ParserKey const& rhs) {
  auto const l = lhs.to_array();
  auto const r = rhs.to_array();
  return std::lexicographical_compare(begin(l),end(l), begin(r), end(r));
}

But it carries the overhead of pressing your members into an iterable container. If you don't want that, you might have to reimplement a lexicographical compare yourself.

CodePudding user response:

In C 20 you can do this: (at class scope)

friend auto operator<=>(const ParserKey &, const ParserKey &) = default;

Don't forget to #include <compare>.

This will give you all 6 relational operators: ==, !=, <, <=, >, >=, performing lexicographical comparison (same as in @FrançoisAndrieux's answer).

  • Related