我的项目中有一张地图。 每次插入新元素时,我都希望确保插入的新元素的键至少是地图中其他元素的最小宽度。为此,我写了一个自定义比较类,如下所示:
class PulseCompare
{
public:
PulseCompare(int minwidth_):minwidth(minwidth_){};
bool operator()(const int x, const int y) const {
if(abs(x-y)>minwidth) return false;
else return true;
}
private:
int minwidth;
};
并创建了这样的地图:
std::map<int,float,PulseCompare> pulsemap(PulseCompare(256));
在插入元素之前,我使用map.find
方法,如下所示:
if ( pulsemap.find(1600) == pulsemap.end() ) {
// not found so I can insert
} else {
// found
}
但问题是,当map尝试通过交换x
和y
的值来使用上述比较函数进行反思性比较时,对于两个案例,它都会得到true
<
和>
在std::map::key_comp
here的cplusplus文档页面上,它说出来并引用
地图对象的比较对象在构造时设置。其类型(成员key_compare)是地图模板的第三个模板参数。默认情况下,这是一个较小的对象,它返回与运算符“&lt;”相同的。
此对象确定容器中元素的顺序:它是一个函数指针或一个函数对象,它接受两个与元素键相同类型的参数,如果第一个参数被认为是在第二个是它定义的严格弱序,否则就是假。
如果key_comp以反射方式返回false,则认为两个键是等效的(即,无论键作为参数传递的顺序如何)。
但这并没有说明它是反射性true
的情况。谁能告诉我它的行为会是什么呢?或者我应该只通过迭代整个地图来进行间隔比较吗?
答案 0 :(得分:9)
std::map
中使用的比较器必须提供strict weak ordering个对象。 std::map
实例将产生未定义的行为。注意:让比较器提供总排序通常会更容易。
此外,让我们描述严格的弱排序需要什么。在这里,我将摘录 C ++ 2011,第25.4节。
Compator comp;
我将引用comp(lhs, rhs)
作为返回布尔值的函数。将其视为lhs < rhs
。equiv(lhs, rhs)
。这被定义为(!comp(lhs, rhs) && !comp(rhs, lhs))
。所以,!(lhs < rhs) && !(rhs < lhs)
。我们需要遵守以下规则:
comp(a, b) && comp(b, c) implies comp(a, c)
equiv(a, b) && equiv(b, c) implies equiv(a, c)
答案 1 :(得分:4)
为什么不将它用作比较器?
return minwidth < (y - x);
以下是一个工作示例:http://coliru.stacked-crooked.com/a/e115d3a2f6714773
答案 2 :(得分:1)
实际上,如果你用这种方式重写比较器,它应该可以工作:
bool operator()(const int x, const int y) const {
if(abs(x-y)<=minwidth) return false;
else return x < y;
}
在插入之前你不需要使用find,你正在做双重工作。只是尝试插入,如果这样的键存在,map将拒绝该插入。 std::map::insert
也会返回std::pair<iterator,bool>
,因此您可以检查插入是否成功。