std :: map操作符的符合性[]

时间:2019-05-18 09:13:31

标签: c++ c++11

我正在尝试解决代码中的错误,似乎我不能真正理解标准中对std :: map :: operator []的要求,或者至少在STL中有问题这是我的编译器附带的(VS2013,仍在尝试使用不同的工具集)。

我可能会误用的std :: map定义了提供Compare类型作为其第三个模板参数,该参数使我使用的某些关键对象与其他某些对象等效。就我的理解而言,尊重标准(23.2.4.2)中给出的对等定义:如果!(a<b)!(b<a),则a和b是等效的。

我面临的问题是,根据插入顺序,有时它还会在其中插入具有等效功能的键。

这是我最后遇到的最小示例:

#include <map>
#include <cassert>

struct Foo {
  int x;
  char c;
};

struct FooLess {
  bool equal_c( const Foo& f1, const Foo& f2) const {
    return f1.c == f2.c;
  }

  bool operator() (const Foo& f1, const Foo& f2) const {
    return !equal_c(f1, f2) && f1.x < f2.x;
  }
};

using namespace std;

int main(int , char* [])
{
  FooLess lt;
  assert( !lt( Foo {1, 'a'}, Foo{3, 'a'}) );
  assert( !lt( Foo {3, 'a'}, Foo{1, 'a'}) );

  map<Foo, string, FooLess> m;

  m[Foo{ 2, 'b'}] = "Foo(b)"; 
  m[Foo{ 3, 'a'}] = "Foo(A)"; 
  m[Foo{ 4, 'c'}] = "Foo(c)";

  // does not hold! 
  assert ((m[Foo{1, 'a'}] == "Foo(A)") );

  m[Foo{ 1, 'a'}] = "Foo(a)"; 

  // does not hold!
  assert(m.size() == 3); 
    return 0;
}

至于我对标准的阅读,断言应该成立。

  

23.4.4.3地图元素访问[map.access]   T&运算符[](const key_type&x);

     

1效果:如果地图中没有等效于x的键,则将value_type(x,T())插入地图。

     

2要求:key_type必须为CopyConstructible,而mapd_type必须为DefaultConstructible。

     

3返回:对* this中与x对应的mapping_type的引用。

     

4复杂度:对数。

我为什么错了?是吗?

1 个答案:

答案 0 :(得分:4)

问题在于FooLess并没有描述严格的弱排序,而是部分排序。

有关详细信息,请参见C++ named requirements: Compare

例如:

Foo a {1, 'a'};
Foo b {2, 'b'};
Foo c {1, 'c'};
FooLess comp;
assert(comp(a, b) && comp(b, c)); // Should imply comp(a, c)
assert(!comp(a, c));              // But doesn't due to only partial ordering

只要地图中或搜索的所有键都具有唯一的.c,您的比较器就可以工作。