检测插入std::set中的坏项



假设我在集合中有一个自定义类型,并且只有当所有项在某些属性上具有相同的值时,集合/排序才有意义…如果插入一个值不同的项,模型就会被搞砸,我想保护它。

我想也许比较函数可能是一个我们可以测试的地方(作为断言或异常),以标记问题和/或防止项目被插入。例如,对于TypeName,如果重要属性不相等,operator<()总是返回false。

这合理吗?

我猜把它放在比较器中可能会有问题,因为你没有任何保证它什么时候会被调用。也许某些虚构的实现在项目数量很少时将项目存储在列表中,并且直到稍后才调用比较器?

可能最简单的方法是将std::set包装在执行这些断言的保护性外部类中。

class MySet {
  private:
     std::set<myFunkyType> myType;
  public:
     void insert(myFunkyType type) {
        assert(!type.isFunky(), "funk violation");
        // and so on
     }
     // all other members other than insertion or mutation just delegate to the
     // underlying set

}

如果您的std::set是自定义类的实现细节,那么它应该取决于您的类的公共成员函数,以确保无效元素不会插入到您的集合中。否则,如果你需要一个数据结构来传递你的对象集合,使用std::map来代替,为你的类提供一个键生成函数,并把你的错误检测代码放在那里。

请记住,set元素和map键一样,就其顺序而言应该是不可变的;基于可变状态的排序很糟糕

operator<的想法听起来有点可疑。这仅仅意味着这些元素被排在最后。xx<y==false中所有y中最大的元素,x<x==false必须始终保持不变。但如果你能接受的话,也没关系。

在你的op<如果发现不能建立严格的弱排序,那么唯一合理的做法就是抛出异常。任何类型的插入,或从op><可能会打破集合的内部约束。>

包装不是真正必要的,因为包装后的insert()的行为可能是相同的(也就是说,抛出一个异常)。

唯一可能使包装更有吸引力的是关于您的标准库实现是否足够好以能够处理抛出比较器的任何不确定性。我怀疑许多标准库实现在该操作上的异常安全性是否很强。

最新更新