【问题标题】:Detecting a bad item inserted into a std::set检测插入到 std::set 的坏项目
【发布时间】:2011-09-23 18:50:23
【问题描述】:

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

我想也许比较函数可能是我们可以测试它(作为断言或异常)的地方,以标记问题和/或防止插入项目。例如,在 TypeName 上,如果重要属性不相等,则 operator

这样合理吗?

【问题讨论】:

    标签: c++ algorithm stl


    【解决方案1】:

    我猜将它放在比较器中可能会出现问题,因为您无法保证何时调用它。当项目数量很少并且直到稍后才调用比较器时,也许某些神话实现将项目存储在列表中?

    可能最简单的方法是将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
    

    }

    【讨论】:

    • 公共继承怎么样? MySet is 真的是 a 集合,你不必编写所有的包装函数...
    • @yi_H:我的理解是 STL 容器并不是真正设计为子类化的,尽管我忘记了原因。
    • @Jeff:如果我只是想阻止它被插入,也许不是问题 - 但是如果我想提醒它,这是一个好点。
    • 这是一种写断言的特殊方式;)
    【解决方案2】:

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

    请记住,作为映射键的集合元素在其顺序方面应该是不可变的;基于可变状态的排序闻起来很糟糕。

    【讨论】:

    • 我从未说过它是可变的。当然,拥有该集合的控制类应该对此进行检查,但我想确定一下,因为这将是一种难以追踪的错误。
    【解决方案3】:

    operator&lt; 的想法听起来有点可疑。这仅仅意味着这些元素是最后排序的。 x 是最大元素 iff x&lt;y==false 对于所有 y,并且 x&lt;x==false 必须始终保持。但如果你能接受,那就没关系。

    【讨论】:

      【解决方案4】:

      当在你的操作中

      恕我直言,包装并不是真正必要的,因为包装的 insert() 的行为可能是相同的(即抛出异常)。

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

      【讨论】:

      • 我认为实现应该足够强大:if an exception is thrown by an insert() function while inserting a single element, that function has no effects. - 这也不难实现:在确定新项目的位置之前不要开始修改容器(并成功为其分配了节点)。
      • @visitor:因此mightuncertainty的模糊词。你也说他们应该,但我真的怀疑这个领域是否经过了彻底的测试,而且由于我们不知道 OP 对可移植性的关心程度,我们至少应该让他考虑一下。甚至测试它。
      • 不,单元素插入函数是防异常的,这是语言标准中的一般要求。 - 你的回答很有道理,我只是想指出这些担忧可能是没有根据的。
      • @visitor:当有广泛的编译器可以将非常量引用绑定到临时文件(msvc)时,我认为怀疑一个实现是否同样很好地实现了某些其他东西是一件非常合理的事情
      猜你喜欢
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 2018-02-13
      • 2011-04-06
      • 1970-01-01
      相关资源
      最近更新 更多