我在理解std::set
(或std::map
等)如何识别唯一键时遇到问题。我想要做的是在boost::shared_ptr
中包装一个struct对象,然后将该共享指针存储在std::set
容器中:
假设结构是一种颜色:
struct Color {
float r;
float g;
float b;
};
然后容器和比较函数对象在另一个类中定义:
class AnotherClass {
typedef boost::shared_ptr<Color> ColorPtr;
public:
struct ColorCompare {
bool operator()(const ColorPtr &a, const ColorPtr &b) const {
return (a->r > b->r) && (a->g > b->g) && (a->b > b->b);
}
};
private:
// Container definition
std::set<ColorPtr, ColorCompare> colors;
};
上面的代码无法根据包装的shared_ptr
结构唯一标识Color
个对象。我一直认为std::set
容器会对两个对象运行一个比较函数,如果它们都不大于或小于另一个 - 它会假设它们是相等的。请注意,我不能使用默认shared_ptr::operator<()
和less<...>
,因为该实现基于指针地址。
我错过了什么?
P.S。我在shared_ptr
内包装颜色,因为我需要在某个时刻知道它们的引用计数(并删除引用计数为1的颜色 - 即仅由std::set
容器本身引用)。有没有更好的方法来获得相同的结果?
答案 0 :(得分:4)
比较需要是严格的弱排序,而不是你的。 (例如,如何排序(1,0,0)和(0,1,0)?)执行此操作:
return (a->r > b->r) ||
((a->r == b->r) && (a->g > b->g)) ||
((a->r == b->r) && (a->g == b->g) && (a->b > b->b) );
这是元素元组的标准词典排序。
请注意,您通常会编写!(b->r > a->r)
而不是a->r == b->r
,因此您不会引入依赖于兼容的相等运算符,但在这个简单的浮点数情况下我们没问题。 / p>
顺便说一句,您不需要struct
,您只需声明static bool ColorCompare(...);
函数即可。另一个选择是直接在operator<
中定义struct Color
以使所有内容都自包含(因此您只需要一个通用的解除引用比较器(智能)指针)。