在使用映射时,我有时会在使用自己的数据类型定义插入到映射中的比较函数时遇到一些问题。例如,现在我有一个这样的结构:
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;
}
对于比较,我覆盖了操作符(),我的想法是这样做:
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 <
我过去处理过这个问题,但我不清楚如何避免它,或者有哪些常见的方法来处理这样的事情,以确保它适用于每种情况
有几件事要做:
- 定义比较器类(在您的例子中是comp_triple_key),为triple_key定义
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;
}
越简单越好。请与下面的方案逐一比较:
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;
}
#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;
}