0
#include <iostream>
#include <set>
#include <algorithm>

class A
{
private:
    int n;
public:
    A(int n_):n(n_){}
    friend bool operator < (const A& a1, const A& a2) //why must be friend, but cannot be member func
    {
        return a1.n < a2.n;
    }

    friend std::ostream& operator<<(std::ostream& os, const A& a)
    {
        os << a.n;
        return os;
    }

    friend class MyLess;

};

class A definition is listed above

class MyLess
{
public:
    bool operator()(const A& a1, const A&a2)
    {
        return a1.n%10 < a2.n%10;
    }

};

int main()
{
    std::multiset<A, MyLess> st2;
    st2.insert(A(11));
    st2.insert(A(2));
    st2.insert(A(5));
    st2.insert(A(19));
    std::cout << "count: " << st2.count(A(2)) << "\n"; //compile error
}

multiset with self-defined comparison rules. when call multiSetObject.count() has compile error? why last line has compile error, if I define st2 using std::multiset<A>, then call st2.count(), then it's ok?

Also, in class A, when I overload operator<. why it must be a friend function, but cannot be member function

Compile error:

[ 50%] Building CXX object CMakeFiles/test13.dir/main.cpp.o
In file included from /usr/include/c++/5/set:60:0,
                 from /home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:2:
/usr/include/c++/5/bits/stl_tree.h: In instantiation of ‘std::pair<std::_Rb_tree_const_iterator<_Val>, std::_Rb_tree_const_iterator<_Val> > std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::equal_range(const _Key&) const [with _Key = A; _Val = A; _KeyOfValue = std::_Identity<A>; _Compare = MyLess; _Alloc = std::allocator<A>]’:
/usr/include/c++/5/bits/stl_tree.h:2320:61:   required from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::count(const _Key&) const [with _Key = A; _Val = A; _KeyOfValue = std::_Identity<A>; _Compare = MyLess; _Alloc = std::allocator<A>; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type = long unsigned int]’
/usr/include/c++/5/bits/stl_multiset.h:650:30:   required from ‘std::multiset<_Key, _Compare, _Alloc>::size_type std::multiset<_Key, _Compare, _Alloc>::count(const key_type&) const [with _Key = A; _Compare = MyLess; _Alloc = std::allocator<A>; std::multiset<_Key, _Compare, _Alloc>::size_type = long unsigned int; std::multiset<_Key, _Compare, _Alloc>::key_type = A]’
/home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:78:45:   required from here
/usr/include/c++/5/bits/stl_tree.h:1727:4: error: no match for call to ‘(const MyLess) (const A&, const A&)’
    if (_M_impl._M_key_compare(_S_key(__x), __k))
    ^
/home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:38:10: note: candidate: bool MyLess::operator()(const A&, const A&) <near match>
     bool operator()(const A& a1, const A&a2)
          ^
/home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:38:10: note:   passing ‘const MyLess*’ as ‘this’ argument discards qualifiers
In file included from /usr/include/c++/5/set:60:0,
                 from /home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:2:
/usr/include/c++/5/bits/stl_tree.h:1729:9: error: no match for call to ‘(const MyLess) (const A&, const A&)’
    else if (_M_impl._M_key_compare(__k, _S_key(__x)))
         ^
/home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:38:10: note: candidate: bool MyLess::operator()(const A&, const A&) <near match>
     bool operator()(const A& a1, const A&a2)
          ^
/home/roaddb/Desktop/ReviewCPPBook/Video/test13/main.cpp:38:10: note:   passing ‘const MyLess*’ as ‘this’ argument discards qualifiers

1 Answers1

0

The big hint is in

note:   passing ‘const MyLess*’ as ‘this’ argument discards qualifiers

multiset is going to provide a const MyLess, so the Function call operator must be const so that it will be compatible with a const this.

Use

bool operator()(const A& a1, const A&a2) const 
                                         ^ added

instead of

bool operator()(const A& a1, const A&a2)
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Thanks! My second question "Also, in class A, when I overload operator<. why it must be a friend function, but cannot be member function" also has the same problem. If I add a const in member function operator<(), then it's ok – Tongheng CHEN Oct 30 '19 at 03:43
  • @TonghengCHEN unless I am horribly mistaken, you can discard the MyLess functor entirely and use the `operator <` overload either as a free friend function or a `const` member function. [It is convention that the operator be a free function](https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading). I suspect there are tactical reasons for this convention, but I must admit to not knowing them. – user4581301 Oct 30 '19 at 03:47