我在c:
中定义了一个新的struct
typedef struct TypedObject {
ObjectType type;
void * value;
} TypedObject;
其中objecttype是一个枚举:
typedef enum ObjectType {
type_node,
type_int,
type_error,
} ObjectType;
我想创建一组C TypedObject
指针,从以前的问题中,我知道我需要超载operator()
,以便在插入集合的TypedObject
指针之间进行比较。
因此,我按照以下方式进行操作:
#ifdef __cplusplus
typedef struct {
bool operator() (const TypedObject *lhs, const TypedObject *rhs){
return (lhs->type==rhs->type) && (lhs->value==rhs->value);
}
} ObjComparator;
#endif
假设我定义了一个集:
std::set<TypedObject *, ObjComparator> mySet;
您可以假设我使用迭代器进行迭代。
我想将TypedObject x
插入集合。我使用mySet.insert(&x)
插入其地址。但是,一旦使用mySet.find(&x)
,它将无法找到x
。对operator()
进行了调用,但并未按预期进行比较。
知道我超负荷operator()
的方式可能会出现什么问题?我究竟做错了什么?另外,我是否应该超载其他版本的运算符,例如&lt;或==?
您提供的Comparator
类应实现订单比较,以便std::set
可以使用它来构建二进制搜索树。
这意味着您的operator()
不应对称 - 默认情况下它是"小于"比较。
通常,Comparator
类的operator()
应该代表您的班级的严格订单关系,因此应为
- 传递-
C(a,b) && C(b,c)
表示C(a,c)
- 反对称 -
C(a,b)
表示!C(b,a)
- 总计-
!C(a,b) && !C(b,a)
的意思是" A和B相等"
"平等"的最后一个定义是std::set
调用set::find
时使用的。
解决方案:虽然您肯定可以提出一些订购以满足上述规则的订购,但也许您可以使用一些重构来完成。
如果您的TypedObject
s具有"地址身份"(即任何对象仅等于自身(,则您可以使用默认比较 - 它非常适合指针:
std::set<TypedObject *> mySet;
如果您需要比较成员,则通常的方法将是这样的:
bool operator() (const TypedObject *lhs, const TypedObject *rhs)
{
if(lhs->value < rhs->value) return true;
if(rhs->value < lhs->value) return false;
return (lhs->type < rhs->type)
}
请注意,如何仅在operator<
上为会员归还。实际上,最好定义operator<
比较TypedObject
s,然后从指针Comparator
调用它。
最后,如果您的set
拥有对象(即离开集合时对象被破坏(,那么也许最好只使用
std::set<TypedObject> mySet;
使用operator<
为TypedObject
重载。您仍然可以从集合中获得对象的指针,并在C API中使用它们,并且您无需处理额外的比较器类和内存管理。
您的订单比较是错误的,因为基于平等,它将无法创建BST,因此正确的代码应如下(Note&lt;在比较器中(
typedef enum ObjectType {
type_node,
type_int,
type_error,
} ObjectType;
typedef struct {
ObjectType type;
void * value;
} TypedObject;
typedef struct {
bool operator() (const TypedObject *lhs, const TypedObject *rhs){
return (lhs->type==rhs->type) && (lhs->value<rhs->value);
}
} ObjComparator;
int main()
{
std::set<TypedObject *, ObjComparator> mySet;
TypedObject obj;
obj.type=type_int;
obj.value=(void*)new int;
//*(obj.value)=4;
auto insert = mySet.insert(&obj);
std::cout<<insert.second<<std::endl;
if(mySet.find(&obj) == mySet.end())
{
std::cout<<"Not Found..."<<std::endl;
}
else
{
std::cout<<"Found..."<<std::endl;
}
return 0;
}