为什么 c++ 中的自定义比较器需要额外的 'const' 关键字

Why custom comparator for set in c++ requires extra 'const' keyword

我正在解决 leetcode OJ 上的一个问题,我必须在 C++ 中使用自定义比较器来设置。

typedef pair<pair<int,int>,int> ppi;

class comp
{
    public:
    bool operator()(const ppi & p1, const ppi & p2)
    {
        if(p1.first.first == p2.first.first)
        {
            if(p1.first.second == p2.first.second) return p1.second > p2.second;
            else return p1.first.second > p2.first.second;
        }
        else
            return p1.first.first > p2.first.first;
    }
};

当我试图从集合中删除一个元素时,这给我一个错误,看起来像:

set<ppi, comp> customStack;
.
.
.
customStack.erase({{currentFrequency, currentAddress},val});

错误:

In file included from prog_joined.cpp:1:
In file included from ./precompiled/headers.h:50:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/map:60:
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_tree.h:779:4: error: static_assert failed due to requirement 'is_invocable_v<const comp &, const std::pair<std::pair<int, int>, int> &, const std::pair<std::pair<int, int>, int> &>' "comparison object must be invocable as const"
          static_assert(
          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_tree.h:1997:31: note: in instantiation of member function 'std::_Rb_tree<std::pair<std::pair<int, int>, int>, std::pair<std::pair<int, int>, int>, std::_Identity<std::pair<std::pair<int, int>, int>>, comp, std::allocator<std::pair<std::pair<int, int>, int>>>::_S_key' requested here
          if (_M_impl._M_key_compare(_S_key(__x), __k))
                                     ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_tree.h:2534:38: note: in instantiation of member function 'std::_Rb_tree<std::pair<std::pair<int, int>, int>, std::pair<std::pair<int, int>, int>, std::_Identity<std::pair<std::pair<int, int>, int>>, comp, std::allocator<std::pair<std::pair<int, int>, int>>>::equal_range' requested here
      pair<iterator, iterator> __p = equal_range(__x);
                                     ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_set.h:685:21: note: in instantiation of member function 'std::_Rb_tree<std::pair<std::pair<int, int>, int>, std::pair<std::pair<int, int>, int>, std::_Identity<std::pair<std::pair<int, int>, int>>, comp, std::allocator<std::pair<std::pair<int, int>, int>>>::erase' requested here
      { return _M_t.erase(__x); }
                    ^
Line 39: Char 25: note: in instantiation of member function 'std::set<std::pair<std::pair<int, int>, int>, comp, std::allocator<std::pair<std::pair<int, int>, int>>>::erase' requested here
            customStack.erase({{currentFrequency, currentAddress},val});
                        ^
1 error generated.

在比较器中添加 'const' 后(第 4 行):

class comp
{
    public:
    bool operator()(const ppi & p1, const ppi & p2)const

这对我有用。

添加该额外关键字的原因是什么?

通过将 const 添加到该成员函数的末尾,您使其成为一个 const 成员函数,这意味着它不可能修改您的任何成员变量。因为调用 non-const 成员函数可以修改对象,所以如果对象是 const,则不能调用它。

std::set 的 erase 成员函数要求 operator() 是 const 以阻止它在您没有意识到的情况下修改其集合中的对象。

如果任何成员函数可以是 const,那么它应该是 const,就像您声明或作为参数接收的任何变量一样。