std::set和boost::shared_ptr唯一密钥标识问题

std::set and boost::shared_ptr unique key identification issues

本文关键字:唯一 密钥 问题 ptr 标识 shared set boost std      更新时间:2023-10-16

我在理解std::set(或std::map等)如何识别唯一密钥方面遇到问题。我想做的是将一个结构对象包装在boost::shared_ptr中,然后将该共享指针存储在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;
};

上面的代码无法根据封装的Color结构唯一标识shared_ptr对象。我一直认为std::set容器会在两个对象上运行一个比较函数,如果它们都不大于或小于另一个,它会假设它们相等。注意,我不能使用默认的shared_ptr::operator<()less<...>,因为该实现是基于指针地址的。

我错过了什么?

p.s.我在shared_ptr中包装颜色,因为我需要知道它们在某个点的引用计数(并删除引用计数为1的颜色,也就是说,仅由std::set容器本身引用)。有没有更好的方法可以得到同样的结果?

比较需要是严格的弱排序,而您的不是。(例如,(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,这样就不会引入对兼容的相等运算符的依赖,尽管在这个简单的浮点情况下,我们可以。

顺便说一下,您不需要struct,只需声明一个static bool ColorCompare(...);函数即可。另一种选择是直接在struct Color中定义一个operator<,使所有内容都是自包含的(因此您只需要一个用于(智能)指针的通用去引用比较器)。