0

I'm getting the error invalid operands to binary expression when I try to compile a project that uses std::sort.

I'm using std::sort like this:

vector <record> vrec;
...
sort(vrec.begin(), vrec.end());

I've already overloaded the < operator like this:

bool operator< (record &r1, record &r2) { ... }

And this is a excerpt of the error message I get:

invalid operands to binary expression ('const record' and 'const record')

operator()(const _T1& __x, const _T1& __y) const {return __x < __y;}

                                                         ~~~ ^ ~~~
mshindal
  • 578
  • 6
  • 17
  • 12
    Post your errors. We strange people can read your strange errors. – Joseph Mansfield Feb 10 '14 at 14:33
  • 6
    Nope. Crystal ball still cloudy. – Jon Feb 10 '14 at 14:33
  • 1
    The operator should be a global function which takes `const` references to its arguments. – David G Feb 10 '14 at 14:34
  • @Jon You should get that checked out. – Captain Obvlious Feb 10 '14 at 14:34
  • 1
    Your question needs to be on SO, though, not on PasteBin – sehe Feb 10 '14 at 14:36
  • Why am I getting downvoted exactly? – mshindal Feb 10 '14 at 14:37
  • 1
    @cardinals7879 exactly? I don't know, but a good approximation for the reason is that you asked a question that 1. lacks research effort (this is an extremely common error, and repeated endless times on SO), 2. you didn't provide enough information to be able to deduce the error, 3. and even when you did, you forced us to go to an external site in order to see the code, which indicates that 4. you didn't bother reading the site FAQ. –  Feb 10 '14 at 14:41
  • oh, I had to mark the member function `this` arg as const by making the signature `bool operator<(const X& rhs) const {...}` which I don't feel is immediately intuitive. – DWR Sep 13 '20 at 14:33

2 Answers2

5

operator< must get the parameters by value (const reference or copy), instead of reference:

bool operator<( const record& lhs , const record& rhs ) 
{
    return /* whatever comparison criteria you have */;
}
Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • why? I think it's good style, but not at all required – sehe Feb 10 '14 at 14:35
  • @sehe: I'm not sure whether or not it *should* be required, but GCC's implementation of `std::sort` does require it. – Mike Seymour Feb 10 '14 at 14:41
  • @sehe [`std::less`](http://en.cppreference.com/w/cpp/utility/functional/less) `operator()`signature is `bool(const&,const&)`. It uses `operator<()`. Since the OP operator is non const, the parameters cannot be forwarded to OP `operator<`. Thats the error. – Manu343726 Feb 10 '14 at 14:42
  • Ah. I forgot that `std::less` is the first hub that relays to `operator<`. Quite right. +1 – sehe Feb 10 '14 at 14:44
  • 1
    @Manu343726 But `std::sort` does not use `std::less`, it uses `operator<` directly (at least it should, it looks like GCC's implementation might use `less`). – interjay Feb 10 '14 at 14:47
  • @interjay ok, but [`std::sort`](http://en.cppreference.com/w/cpp/algorithm/sort) comparer should have the signature `bool(const&,const&)` (Technically, it should take the parameters by value. It does not specifiy which way of value pass). Thats the same for the default comparer (`operator<`). – Manu343726 Feb 10 '14 at 14:49
  • @Manu343726 The standard does not specify such a signature anywhere that I can see. It only specifies that the comparer should not attempt to modify its arguments. – interjay Feb 10 '14 at 14:52
  • @Manu343726: The site you link to says "The signature does not need to have `const &`"; and there's no indication in the standard that the arguments must be `const`. The only restriction I can find is in C++11 25.4/2 "It is assumed that `comp` will not apply any non-constant function through the dereferenced iterator." (and even then, that refers to a comparator argument, not `operator<`). – Mike Seymour Feb 10 '14 at 14:52
0

Your comparison operator's signature does not match what std::less expects: const reference parameters.

sort3a.cpp:127:6: note: candidate function not viable: 1st argument ('const record') would lose const qualifier
bool operator< (record &r1, record &r2)

Try redefining it like this:

bool operator< (const record &r1, const record &r2)
{ ... }
Martin J.
  • 5,028
  • 4
  • 24
  • 41