Home > database >  Why custom comparator for set in c requires extra 'const' keyword
Why custom comparator for set in c requires extra 'const' keyword

Time:03-19

I am solving a problem on leetcode OJ where i had to use a custom comparator for set in 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;
    }
};

this is giving me an error when i am trying to delete an element from the set, which looks like:

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

error:

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.

after added 'const' in the comparator (line 4):

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

this worked for me.

What is the reason for adding that extra keyword?

CodePudding user response:

By adding that const to the end of that member function you're making it a const member function, meaning that it cannot possibly modify any of your member variables. Because calling a non-const member function could modify the object, you can't call it if the object is const.

std::set's erase member function requires that operator() be const to stop it from modifying the object's in their set without you realizing.

If any member function can be const then it should be const, just like any variables you declare or take in as arguments.

  • Related