在使用地图时,我在定义比较函数时遇到了一些问题,因为我使用自己的数据类型插入地图。例如,目前我有这样的结构:
typedef struct triple_key{
int int_key;
struct some_data;
unsigned char char_array_key[16];
}triple_key;
其中some_data是这样的:
struct some_data{
int data_length;
unsigned char* data;
}
为了比较,我覆盖了operator(),我的想法是执行以下操作:
class comp_triple_key{
public:
bool operator()(const triple_key &x, const triple_key &y){
if(x.int_key!= y.int_key){
return x.int_key<y.int_key;
}
else{
if(memcmp((x.some_data).data, (y.some_data).data, (x.some_data).data_length) != 0){
return memcmp((x.some_data).data, (y.some_data).data, (x.some_data).data_length) < 0;
}
else{
return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
}
}
};
};
然后地图如下:
std::map<triple_key,int,comp_triple_key> my_map;
有没有更好的方法来比较这些多个键值?在大多数情况下,这是有效的(并且工作正常),但有时我会得到断言:
Expression: invalid operator <
我过去曾经处理过这个问题,但我不清楚如何一般地避免这个问题,或者通常使用哪种方法来确保它适用于所有情况。
答案 0 :(得分:2)
有几件事要做:
operator<
这样的工作:
bool operator<(const triple_key &x, const triple_key &y){
if(x.int_key!= y.int_key){
return x.int_key<y.int_key;
}
else{
if(memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) != 0){
return memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) < 0;
}
else{
return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
}
}
}
然后你可以创建像:
这样的对象std::map<triple_key,int> my_map;
可编辑示例(问题中的固定代码):
#include <map>
#include <iostream>
#include <string>
#include <string.h>
struct some_data{
int data_length;
unsigned char* data;
};
struct triple_key{
int int_key;
some_data somedata ;
unsigned char char_array_key[16];
};
bool operator<(const some_data &x, const some_data &y){
if(x.int_key!= y.int_key){
return x.int_key<y.int_key;
}
else{
if(memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) != 0){
return memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) < 0;
}
else{
return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
}
}
}
bool operator<(const triple_key &x, const triple_key &y){
if(x.int_key!= y.int_key){
return x.int_key<y.int_key;
}
else{
if(memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) != 0){
return memcmp((x.somedata).data, (y.somedata).data, (x.somedata).data_length) < 0;
}
else{
return memcmp((x.char_array_key), (y.char_array_key), 16*sizeof(char))<0;
}
}
}
int main()
{
std::map<triple_key,int> my_map;
}
答案 1 :(得分:1)
越简越好。只需逐一比较这个方案:
bool operator()(const triple_key &x, const triple_key &y){
if (x.int_key < y.int_key)
return true;
if (y.int_key < x.int_key)
return false;
if (lexicographical_compare(x.some_data.data, x.some_data.data + x.some_data.data_length,
y.some_data.data, y.some_data.data + y.some_data.data_length))
return true;
if (lexicographical_compare(y.some_data.data, y.some_data.data + y.some_data.data_length,
x.some_data.data, x.some_data.data + x.some_data.data_length))
return false;
return memcmp(x.char_array_key, y.char_array_key, sizeof(y.char_array_key)) < 0;
}
答案 2 :(得分:0)
#include <iostream>
#include <memory>
#include <map>
using namespace std;
struct some_data{
int data_length;
unsigned char* data;
bool operator < (const some_data& other) const
{
if (memcpy(data, other.data, data_length) < 0)
return true;
else
return false;
}
};
typedef struct triple_key{
int int_key;
struct some_data data;
unsigned char uuid[16];
bool operator < (const triple_key& other) const
{
if (int_key < other.int_key)
return true;
else
{
if (data < other.data)
return true;
else
{
if (memcpy((void*)uuid, (void*)other.uuid, sizeof(uuid)) < 0)
return true;
}
}
return false;
}
}triple_key;
int main()
{
some_data data1;
data1.data = (unsigned char *)malloc(4);
data1.data_length = 4;
some_data data2;
data2.data = (unsigned char *)malloc(5);
data2.data_length = sizeof(5);
triple_key key1;
key1.int_key = 1;
key1.data = data1;
triple_key key2;
key2.int_key = 2;
key2.data = data2;
std::map<triple_key, int> myMap;
myMap[key1] = 1;
myMap[key2] = 2;
cout<<myMap.size()<<endl;
}