C++ 使用std::set和多个比较条件的容器

C++ 使用std::set和多个比较条件的容器,c++,data-structures,stl,C++,Data Structures,Stl,我正在尝试编写一个包含两个std::sets的容器,其中包含使用不同比较器类的相同元素。以下是我的观点,简化: struct Element { // foo and bar are immutable to prevent messing set order up. FooStruct const foo; BarStruct const bar; int someVar; Element(FooStruct foo); Element(Bar

我正在尝试编写一个包含两个
std::set
s的容器,其中包含使用不同比较器类的相同元素。以下是我的观点,简化:

struct Element
{
    // foo and bar are immutable to prevent messing set order up.
    FooStruct const foo;
    BarStruct const bar;
    int someVar;

    Element(FooStruct foo);
    Element(BarStruct bar);
};

class CriterionFoo
{
    // Sorts according to member foo.
    bool operator()(Element* const& arg0, Element* const& arg1);
};

class CriterionBar
{
    // Sorts according to member bar.
    bool operator()(Element* const& arg0, Element* const& arg1);
};

class ElementContainer
{
    typedef std::set<Element*, CriterionFoo> FooSortedSet;
    typedef std::set<Element*, CriterionBar> BarSortedSet;

    FooSortedSet fooSortedSet;
    BarSortedSet barSortedSet;

    // fooSortedSet.find(&Element(myFoo))
    Element* findElement(FooStruct myFoo);
    // barSortedSet.find(&Element(myBar))
    Element* findElement(BarStruct myBar);

    // Inserts in both sets.
    void insert(Element* element);

    // Enter total alienation and existential crisis...
    void erase(BarStruct myBar);
    void erase(FooStruct myFoo);
};
struct元素
{
//foo和bar是不可变的,以防止弄乱设置顺序。
FooStruct const foo;
BarStruct const-bar;
int-someVar;
元素(foostructfoo);
元素(BarStruct bar);
};
类标准
{
//根据成员foo排序。
布尔运算符()(元素*const&arg0,元素*const&arg1);
};
类标准
{
//根据成员栏进行排序。
布尔运算符()(元素*const&arg0,元素*const&arg1);
};
类元素容器
{
typedef std::set foodsortedset;
typedef std::set BarSortedSet;
食物分类集食物分类集;
BarSortedSet BarSortedSet;
//fooSortedSet.find(&元素(myFoo))
元素*findElement(FooStruct myFoo);
//barSortedSet.find(&元素(myBar))
元素*findElement(BarStruct myBar);
//在两个集合中插入。
空白插入(元素*元素);
//进入完全异化和生存危机。。。
无效擦除(BarStruct myBar);
无效擦除(FooStruct myFoo);
};
我想要实现的只是制作一个集合包装器,在log(n)复杂性中找到一个具有两个不同搜索条件的成员
ElementContainer::erase
方法可以很容易地找到这两个条件的
[Foo | Bar]SortedSet::iterator
,但无论如何,我必须天真地遍历另一个条件(这几乎超过了全部条件)。然后,我可以将
[Foo | Bar]SortedSet::const_iterator
引用放在
元素
结构中,只需一步就可以到达另一个集合中相应的迭代器,但这感觉像是一种过度使用


好吧,我不可能是第一个遇到这种情况的人。是否有任何既定的方法可以使用多个标准轻松导航一组元素?特别是在不进行过度工程狂热的情况下?

首先,您需要异构查找:能够使用给定的
BarStruct
myBar
查找
元素
,而无需构建虚拟
元素(myBar)
。这可以通过将以下
操作符()
重载添加到
CriterionBar
(相当于
criterionfo
)来实现:

注意:比较运算符必须是
const
成员函数

此外,您还可以使用代码IS>透明的使这些集合考虑这些额外的比较选项(并将相应的重载添加到例如<代码>查找< /代码>)。例如:

using is_transparent = void;
这并不是绝对必要的,但比您当前正在做的虚拟
元素
要好几英里

在两个
O(log(N))
操作中从两个集合中删除的实际步骤很简单:

void erase(FooStruct myFoo)
{
  auto fooIt = fooSortedSet.find(myFoo);
  Element* elementToErase = *fooIt;
  auto barIt = barSortedSet.find(elementToErase);

  fooSortedSet.erase(fooIt);
  barSortedSet.erase(barIt);
}

看看boost多索引:“我必须天真地遍历另一个”,在删除之前检索元素,这样您就可以同时获得日志(n)搜索的
Foo
Bar
成员……很好的操作符重载技巧,我会考虑到这一点。这两个集合都没有将
元素*
类型作为它们的键值,但我不知道如何使用该引用
查找
。编辑:你可能说得有道理,我想我需要有清醒的头脑来考虑这个问题。@corsel请记住我在那之后所做的编辑。特别是,
是透明的,
是它工作所必需的。@corsel“集合不把
元素*
作为键值”是什么意思?你可以比较/区分/查找元素,这是集合的要点……是的,这是一个混乱的时刻:)我想我可以把这标记为一个答案。答案出来后,似乎很明显。
void erase(FooStruct myFoo)
{
  auto fooIt = fooSortedSet.find(myFoo);
  Element* elementToErase = *fooIt;
  auto barIt = barSortedSet.find(elementToErase);

  fooSortedSet.erase(fooIt);
  barSortedSet.erase(barIt);
}