How can I declare a custom sort function on std::map declaration?
The container std::map
always sorts keys based on their value. Is it possible to make it sort, for example, on the number of bits set upon declaration?
I have a function for counting set bits:
for(size_t i = 0; i < CHAR_BIT * sizeof value; ++i, value >>= 1) {
if ((value & 1) == byteState) ++num_bits;
}
But I do not know how to apply it when declaring the map:
std::map<int, int> myMap = {
{1,2},
{3,4},
//...
}
I've tried to put it as a third parameter in the declaration <int,int,decltype(countSetBits)>
, but with no luck.
Solution 1:
You need to wrap your function in a binary operator, like this:
#include <iostream>
#include <map>
#include <algorithm>
int cntBits(int value) {
int num_bits=0;
for(size_t i = 0; i < 32 ; ++i, value >>= 1) {
if ((value & 1) == 1) ++num_bits;
}
return num_bits;
}
struct cntBitsCmp {
bool operator()(int a, int b) {
return cntBits(a) < cntBits(b);
}
};
Now you can use cntBitsCmp
in a declaration:
std::map<int,int,cntBitsCmp> myMap= {
{128,2},
{3,4},
...
};
Here is a demo on ideone. It correctly orders 128 ahead of 3, because 3 has two bits set, while 128 has only one.
Solution 2:
Since C++11, you can also use a lambda expression instead of defining a comparison function. If you combine this with std::bitset::count instead of using your own counting function, then the code becomes rather short:
auto comp = [](int a, int b) { return std::bitset<32>(a).count() < std::bitset<32>(b).count(); };
std::map<int, int, decltype(comp)> m(comp);
Note: Similar to the solution by Sergey, I'm assuming 32-bit integers for the sake of clarity. Please adapt the code to your needs.
Code on Ideone