Strict Weak Ordering和std :: set / std :: map

时间:2016-02-09 08:21:43

标签: c++ set strict-weak-ordering

#include <iostream>
#include <set>
#include <tuple>

struct Key {
  int field1;
  int field2;

  Key(int field1, int field2) : field1(field1), field2(field2) {}

  bool operator<(const Key& other) const {
    // Is this acceptable?! Seems to work
    if (field2 == 0 || other.field2 == 0) {
      return field1 < other.field1;
    } else {
      return std::tie(field1, field2) < std::tie(other.field1, other.field2);
    }
  }
};

int main() {
    std::set<Key> values{Key(4,3), Key(5,9), Key(5,7), Key(5,8), Key(6,1)};
    std::cout << values.find(Key(5,0))->field2 << std::endl; // Prints '7'
    auto range = values.equal_range(Key(5,0));
    for (auto i = range.first; i != range.second; i++) {
        std::cout << i->field2; // Prints '789'
    }
    return 0;
}

Field2在我的数据中并不总是可用,因此有时我使用通配符值0,它可以匹配field1匹配的任何值。如果我从不插入具有通配符值的元素,并且只在集合中查找它们,这在C ++中是否有效?我可以使用find函数返回在这种情况下的任何值,这在我的代码中很少发生,但希望它在重复调用时会是相同的值。

根据specification,似乎二进制搜索不需要严格的弱排序,这应该是执行查找时数据结构上使用的唯一算法,对吧?或者是否有一些我应该担心的未定义行为?

  

25.4排序和相关操作

     

...对于25.4.3中描述的算法以外的算法   正确地说,comp必须对值进行严格的弱排序......

     

25.4.3二进制搜索

1 个答案:

答案 0 :(得分:1)

你错了。 std::set::find在二叉搜索树中进行查找(在典型的实现中)。这可能看起来像二进制搜索算法,但25.4.3中的算法通常不用于查找。树只支持非随机访问迭代器,而使用线性迭代器的二进制搜索比使用数据在BST中的知识的查找要慢得多。

std::set的比较器必须符合Compare概念,这需要strict weak ordering

  

如果我从不插入具有通配符值的元素,并且只在集合中查找它们,这在C ++中是否有效?

技术上没有,因为你违反了要求。从包含{x, 0}{x, a}的集合中查找{x, b}时,至少会有不确定的结果。两者都可以找到。如果这不重要,那么我怀疑典型的实施会带来麻烦。你所做的并不能保证按标准工作,这足以让大多数人回避它。