std::multiset 定义用于插入和比较的比较器

std::multiset define comparator for insertion and comparison

我在我的游戏中使用 std::multiset 指向对象的指针来实现 Z 排序,因此我不需要在每次插入时对结构进行排序。我使用比较器按对象的深度插入:

struct rendererComparator
{
    bool operator ()(const Renderable* r1, const Renderable* r2) const
    {
        return r1->depth < r2->depth;
    }
};

std::multiset<Renderable*, rendererComparator> m_Renderables;

然而,当涉及到擦除多重集中的元素时,对 erase 的调用会删除所有具有相同深度的元素,这是不受欢迎的。我尝试了这个问题中的建议:In std::multiset is there a function or algorithm to erase just one sample (unicate or duplicate) if an element is found

auto iterator = m_Renderables.find(renderable);
if (iterator != m_Renderables.end())
{
    m_Renderables.erase(renderable);
}

由于比较器的存在,仍然擦除所有具有相同深度的元素。

是否可以在没有提升的情况下为 std::multiset 定义 2 个比较器? ()一个插入一个比较?

谢谢

编辑:Jignatious 指出我没有擦除迭代器(我打字错误)。我使用 std::find_if

解决了它
auto iterator = std::find_if(m_Renderables.begin(), m_Renderables.end(), [renderable](const Renderable* r1) { return r1 == renderable; });
if (iterator != m_Renderables.end())
{
    m_Renderables.erase(iterator);
}

问题出在这一行:

m_Renderables.erase(renderable);

它会删除具有 相同值 所有 个元素。

您需要使用 find() 函数调用中的迭代器进行擦除。这将擦除迭代器指向的单个元素:

m_Renderables.erase(iterator);

注意 std::multiset::find() returns 一个迭代器指向元素的下界(或第一个),如果它存在则在多集中搜索,否则指向结束元素迭代器。

您可以将 std::set 与比较器一起使用,而不是多重集,如下所示:

struct Element
{
    int value;

    Element(int v)
    {
        value = v;
    }

    bool operator() (Element* const& left, Element* const& right) const
    {
        if (left->value == right->value)
            return (left < right);

        return left->value < right->value;
    }
};

它将像 multimap 一样存储多个值,但在擦除时没有 'erase all',在插入时没有替换相同的值,并且通过引用正确查找。


std::set<Element*, Element> set;
set.insert(new Element(10));
auto last = new Element(10);
set.insert(last); // 10 10 like in multiset
set.erase(last); // will delete proper references