Error using std::find with operator== - c++

I am getting an error using std::find on the following structure ...
struct ComplianceOrderRecord {
explicit ComplianceOrderRecord(IOrder& order);
bool operator ==(const ComplianceOrderRecord& other) const;
double price;
};
inline bool ComplianceOrderRecord::operator ==(const ComplianceOrderRecord& other) const {
return price == other.price;
}
I use it as follows...
inline void Compliance::RemoveComplianceOrderRecord(const ComplianceOrderRecord& order) {
auto it = std::find(m_compliantOrderList.begin(),
m_compliantOrderList.end(), order);
if(it == m_compliantOrderList.end()) {
return;
}
m_compliantOrderList.erase(it);
}
The error is...
error C2679: binary '==' : no operator found which takes a right-hand operand of type 'const ComplianceOrderRecord' (or there is no acceptable conversion)
Any help in understanding this error would be very appreciated.

Your operator== should be a const member, or even better, a freestanding function.

This error can be reproduced if m_compliantOrderList is not a container<ComplianceOrderRecord >. (Perhaps it is a container of pointers, or some other completely unrelated class.
Edit:
Your equality operator can compare two instances of ComplianceOrderRecord, but find needs to compare a pointer against an object. Overloading an operator to perform this kind of comparison would be bizarre, so you could use find_if with a custom predicate, such as:
struct RecordIsEqualTo
{
const ComplianceOrderRecord* record;
RecordIsEqualTo(const ComplianceOrderRecord& r): record(&r) {}
bool operator() (const ComplianceOrderRecord* r) const { return *record == *r; }
};
std::find_if(m_compliantOrderList.begin(), m_compliantOrderList.end(),
RecordIsEqualTo(order) );
or a lambda version thereof.

Your operator== function should be const. As it is, you can't call it on a const object (or a reference to const.

Try a const method:
inline bool ComplianceOrderRecord::operator ==(const ComplianceOrderRecord& other) const {
return price == other.price;
}

Related

C++ finding class in vector using std::find raises errors

I'm trying to find a SnekNode object in an std::vector using
auto it = std::find(snek_node_container.begin(), snek_node_container.end(), snek_node);
but it raises a compiler error:
Error C2676 binary '==': 'SnekNode' does not define this operator or a
conversion to a type acceptable to the predefined operator
which points to the xutility file as source which is not very helpful. When I try to define a == function in the class such as:
SnekNode operator== (const SnekNode& rhs) {
return (*this == rhs);
}
I get another compilation error:
C2451 conditional expression of type "SnekNode" is illegal
which also points to the xutility file which again, sadly doesn't help me. What am I doing wrong here? Thanks in advance!
operator== should return bool.
Also, you need to compare the members individually. In your code you just call operator== again, causing infinite recursion.
What you can do is use the operator== in operator!= to save typing, e.g.:
struct SnekNode
{
bool operator== (const SnekNode& rhs) const {
return a == rhs.a &&
b == rhs.b &&
c == rhs.c;
}
bool operator!= (const SnekNode& rhs) const {
return !(*this == rhs);
}
// auto operator<=>(const SnekNode&) const = default; // C++20
int a{0};
int b{1};
int c{2};
};
With C++20 you can use default comparisons (spaceship operator).
Live demo

Overloading less than operator in c++ for use in std::sort

I have a struct defined like this:
struct IFSFunc {
int a;
bool operator<(const IFSFunc& other) {
return a < other.a;
}
};
Since IFSfunc is a struct, access modifier for the operator< should be public.
I also have this code:
#include <algorithm>
std::vector<std::pair<double, IFSFunc>> ifsFuncs;
// fill the vector with various data
std::sort(ifsFuncs.begin(), ifsFuncs.end());
I need to sort ifsFuncs based on the first double in the pair. I don't care about IFSFunc structure, if the double is the same.
However, for std::sort to work, which is defined like this:
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) {
return _Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second);
}
I have to override the less than operator for the second in this case IFSfunc, which I did. However, trying to compile this code gives me the following error:
Error C2678 binary '<': no operator found which takes a left-hand operand of type 'const _Ty2' (or there is no acceptable conversion)
Why?
You need to define that operator as a const member function.
Also, don't just return true for a comparison. That can result in infinite looping.
I just figure it out. The overloaded function signature was wrong, this is what I need:
struct IFSFunc {
int a;
bool operator<(const IFSFunc& other) const {
return a < other.a;
}
};
Notice that the operator< is now a const function.

Array subscript operator on a Matrix

I'm trying to overload the Array subscript operator on a Matrix, however I'm getting an error that I can't understand. The CMazeSquare && operator[] (const tuple &other); is meant to access the CMazeSquare grid** which a matrix of CMazeSquares. I would like to be able to access the CMazeSquare object just by saying grid[someTuple]
CMaze.h:61:17: error: expected unqualified-id before ‘&&’ token
CMazeSquare && operator [] (const tuple &other);
^
I can't for the life of me understand what is wrong here. Please help.
#ifndef CMAZE_H
#define CMAZE_H
struct tuple
{
short x;
short y;
tuple();
tuple(const tuple &other);
tuple(short X, short Y);
tuple operator + (const tuple &other);
};
class CMaze
{
public:
private:
struct CMazeSquare
{
CMazeSquare ();
void Display (ostream & outs);
sType what;
bool vistited;
};
CMazeSquare ** grid;
CMazeSquare && operator [] (const tuple &other); //<- This is the problem
};
#endif
I'm thinking the implementation of the operator would look something like this:
//in CMaze.cpp
CMaze::CMazeSquare && CMaze::operator [](tuple &other)
{
return this[other.x][other.y];
}
This is how operator[] is usually overloaded:
CMazeSquare& operator[] (const tuple &other)
{
return grid[other.x][other.y];
}
const CMazeSquare& operator[] const (const tuple &other)
{
return grid[other.x][other.y];
}
There a few problems with your code:
First, the definition doesn't match the declaration:
CMazeSquare && operator [] (const tuple &other);
vs
CMaze::CMazeSquare && CMaze::operator [](tuple &other)
Note the const missing in the definition parameters
Then you can't say this[...]. It doesn't do what you think it does.
Lastly why are you trying to return an rvalue reference? You need 2 overloads one for const returning a const lvalue reference and one for mutable returning a mutable reference.
the error you got I suppose is because you don't compile in C++11 and the compiler doesn't understand &&.

C++ doesnt overload operator

For some reason, the custom compare seems to be skipped. Never is the debug string printed and the sorting is off.
Can anyone spot what is wrong here?
bool Communication::operator<(const Communication& second) const
{
qDebug() << "Actually sorting";
return (getName().compare(second.getName()) < 0);
}
class Communication
{
public:
bool operator<(const Communication& second) const;
QString getName() const;
void setName(QString nm);
QString commName;
}
void Communication::addComm(vector<Communication*>c)
{
// This is called for sure
lg=c;
std::sort ( lg.begin(), lg.end());
}
Edit:
Below my new approach.
bool Communication::cmp(const Communication* lhs, const Communication* rhs) const
{
return (lhs->getName().compare(rhs->getName()) < 0);
}
...error: no matching function for call to 'sort(std::vector<Communication*>::iterator, std::vector<Communication*>::iterator, <unresolved overloaded function type>)'
Your vector contains pointers:
vector<Communication*> c
but your comparison is for values. You need to implement a comparison for pointers, but this cannot be operator< because you cannot overload that operator for pointers. It should be a function or functor.
bool cmp(const Communication* lhs, const Communication* rhs)
{
return (lhs->getName().compare(rhs->getName()) < 0);
}
std::sort ( lg.begin(), lg.end(), cmp);
Operators won't be overloaded for operators. If you want to sort a sequence of pointers based on a predicate on the pointees you'll need to use a suitable predicate function, e.g.:
std::sort(lg.begin(), lg.end(),
[](Communication const* c0, Communication const* c1){
return *c0 < *c1;
});
You are sorting a vector of Communication*, but your operator< compares const Communication&.

C++ overloading operator< error

Why am I receiving an error when I do not put const in the function bool operator<(const Node& otherNode) //const?
stl_algo.h:91: error: passing 'const Node' as 'this' argument of 'bool Node::operator<(const Node&)' discards qualifiers
Should all the overloaded operators be constant?
class Node {
public:
double coordinate;
bool operator==(const Node& other) const{
return coordinate == other.coordinate;
}
bool operator<(const Node& other) const{
return coordinate < other.coordinate;
}
};
Not all operators, but == and < should definitely be made const, yes. They logically don't modify either of the objects being compared.
The error likely comes from calling a non-const method from a const one, e.g.:
bool isSmaller(const Node& other) const
{
return *this < other;
}
In this case, since the method isSmaller is const, this is implicitly a const object, therefore operator < also has to be const in order for the call within that context to be valid.
From the error message, it appears that Node::operator < is being called on a const object, from a function in stl_algo.h - sorting/ordering functions, hashing functions, etc.
Comparison operators, such as <, >, <=, >=, ==, != should operate on const objects in general, because it makes no sense if any objects being compared can be changed by the comparison. But you could declare the comparisons as non-member functions in order to ensure symmetry between both operands.
class Node {
public:
double coordinate;
};
inline operator<(const Node& lhs, const Node& rhs)
{
return lhs.coordinate < rhs.coordinate;
}
Have you try to delete the const modifier of the method? Also, as #LuchianGrigore sugest, you can use the this keyword:
bool operator< (const Node& other) {
return this.coordinate < other.coordinate;
}