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



我在游戏中使用了一组指向对象的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的调用会删除具有相同深度的所有元素,这是不希望的。我尝试了这个问题中的建议:在std::multiset中,如果找到一个元素但,是否有一个函数或算法可以只擦除一个样本(单播或重复(

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

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

是否可以在没有boost的情况下为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()返回一个迭代器,该迭代器指向在多集合中搜索的元素的下界(或第一个((如果存在的话(,否则指向经过结束元素迭代器的元素。

您可以使用std::set和类似的比较器:来代替multiset

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一样存储多个值,但在擦除时不会"全部擦除",在插入时不会替换相同的值,并通过引用进行正确查找。


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

最新更新