std::set 和 boost::shared_ptr 唯一键识别问题

发布于 2024-12-25 20:29:04 字数 1169 浏览 6 评论 0原文

我在理解 std::set (或 std::map 等)如何识别唯一键时遇到问题。我想做的事情是将一个结构对象包装在 boost::shared_ptr 中,然后将该共享指针存储在 std::set 容器中:

假设该结构是一个color:

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<...> 因为该实现是基于指针地址的。

我缺少什么?

ps 我将颜色包装在 shared_ptr 中,因为我需要在某个时刻知道它们的引用计数(并删除引用计数为 1 的颜色 - 也就是说,仅由 std::set< 引用/code> 容器本身)。有没有更好的方法来获得相同的结果?

I am having issues understanding how std::set (or std::map etc) identify unique keys. The thing I am trying to do is wrap a struct object within boost::shared_ptr and then store that shared pointer within std::set container:

Let's say the struct is a color:

struct Color {
    float r;
    float g;
    float b;
};

Then the container and comparison function object is defined in another class:

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;
};

The code above is failing to uniquely identify shared_ptr objects based on their wrapped Color struct. I always thought that the std::set container would run a comparison function on two objects, and if none of them is greater than or less than the other - it will assume they are equal. Note, that I cannot use default shared_ptr::operator<() and less<...> as that implementation is based on pointer address.

What am I missing?

p.s. I am wrapping colors within shared_ptr since I need to know their reference count at some point (and remove colors that are at ref count 1 - that is, only referenced by std::set container itself). Is there a better way to get the same result?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦情居士 2025-01-01 20:29:04

比较必须是严格的弱排序,而您的则不是。 (例如,(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< 以使所有内容都是独立的(因此您只需要一个用于(智能)指针的通用解引用比较器)。

The comparison needs to be a strict weak ordering, which yours isn't. (For example, how are (1,0,0) and (0,1,0) ordered?) Do this:

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) );

This is the standard lexicographic ordering on a tuple of elements.

Note that you would write !(b->r > a->r) instead of a->r == b->r in general so that you don't introduce a dependence on a compatible equality operator, though in this simple case of floats we're fine.

By the way, you don't need a struct, you can simply declare a static bool ColorCompare(...); function. Another option is to define an operator< directly in the struct Color to make everything self-contained (so you'll just need a generic dereferencing-comparator for (smart) pointers).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文