我正在尝试解决代码中的错误,似乎我不能真正理解标准中对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复杂度:对数。
我为什么错了?是吗?
答案 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
,您的比较器就可以工作。