如何在std :: map声明中声明自定义排序函数?

时间:2013-03-23 15:18:37

标签: c++ sorting dictionary

容器std::map总是根据键值对键进行排序。例如,是否可以对声明时设置的位数进行排序?

我有一个计数设置位的功能:

for(size_t i = 0; i < CHAR_BIT * sizeof value; ++i, value >>= 1) {
  if ((value & 1) == byteState) ++num_bits;
}

但我在宣布地图时不知道如何应用它:

std::map<int, int> myMap = {
  {1,2},
  {3,4},
  //...
}

我试图将它作为声明<int,int,decltype(countSetBits)>中的第三个参数,但没有运气。

3 个答案:

答案 0 :(得分:6)

您需要将函数包装在二元运算符中,如下所示:

#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);
    }
};

现在您可以在声明中使用cntBitsCmp

std::map<int,int,cntBitsCmp> myMap= {
    {128,2},
    {3,4},
    ...
};

这是demo on ideone。它正确地在3之前命令128,因为3设置了两个位,而128只有一个。

答案 1 :(得分:1)

基本上这可以按你的意愿运作:

bool comp(int x , int y ){
    return  __builtin_popcount(x) <  __builtin_popcount(y);
}
int main(){
    bool(*fn_pt)(int,int) = comp;
    std::map<int, int, bool(*)(int,int) > myMap (fn_pt);
    myMap[7]=11;
    myMap[8]=12;
    cout<<myMap.begin()->first<<endl;  // you get 8 instead of 7
}

答案 2 :(得分:0)

C++11起,您也可以使用lambda expression代替定义比较功能。如果将其与std::bitset::count结合使用而不是使用自己的计数功能,则代码将变得很短:

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);

注意:与dasblinkenlight的solution相似,为清楚起见,我假设使用32位整数。 请根据您的需要修改代码。

Code on Ideone