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
我在我的游戏中使用 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