Operator overloading, const and #arguments errors - c++

Have this code in a simple class Time composed of two integers (day/hour) for an arduino project.
bool operator <= (const Time& other) const{
return (day <= other.day && hour <= other.hour);
}
Although I do have an almost identical (and working) other class which uses the same syntax with the same non-static form... I'm getting the following errors :
error: non-member function ‘bool operator<=(const Time&)’ cannot have cv-qualifier
error: ‘bool operator<=(const Time&)’ must take exactly two arguments
I'm afraid that I'm at a loss despite having spent the last half-hour googling similar errors.
Thanks!

You have a non-member comparison operator. It makes sense for it to be a non-member rather than a member, but it requires two arguments, and cannot be const:
bool operator <= (const Time& lhs, const Time& rhs) { .... }
Also, you need to fix the logic of the comparison. I am very lazy so I would do it like this:
#include <tuple>
bool operator <= (const Time& lhs, const Time& rhs)
{
return std::tie(lhs.day, lhs.hour) <= std::tie(rhs.day, rhs.hour);
}
See more on operator overloading here.

error: non-member function ‘bool operator<=(const Time&)’ cannot have cv-qualifier
You cannot add const qualifiers to a non member function.
Let me explain you why
The const after a member function guarantees that this function will not change any member variable of this . Now what would a static function guarantee if you don't have any this to refer to?
error: ‘bool operator<=(const Time&)’ must take exactly two arguments
There are 2 ways of overloading operators. You can make them member functions (without the static), but if you want to compare int and Time for example.. Lets write it out:
in your Time class, write out the following operator:
bool operator<=(int rhs) const {return this.minutes <= rhs;}
now, let us compare our data:
Time time;
int integer;
if(time <= integer) {} //This will compile
if(integer <= time) () //This will not compile
lets see why that is:
if(time <= integer) {} //Will expand to this:
if(time.operator<=(integer)) {}
now can you guess what this does?
if(integer <= time) {} //Will expand to this:
if(integer.operator<=(time)) {}
There is no such operator for a default type like integers, and you can't simply just add one to the integer type.
The solution to this are the static operators.
To cover both cases (int <= Time and Time <= int)
you can write this operator as well in your Time class
static bool operator<=(int lhs, const Time& rhs) {};
The parameters are the left side of the comparison and the right side of the comparison.
I also suggest you to take a look at juanchopanza's link:
See more on operator overloading here.
and this link for the difference between member function operators and non member function operators.

If this operator was declared as a class member function then you need to define it the following way
bool Time::operator <= (const Time& other) const{
return (day <= other.day && hour <= other.hour);
}
Also take into account that the condition inside the operator is invalid.
There should be
bool Time::operator <= (const Time& other) const{
return ( day <= other.day ) && ( other.day > day || hour <= other.hour ) );
}

Related

c++ std::set compare function when object is member of the set

I have a set composed of objects; in order to work the operator< must be defined for ordering the objects inside the set. If I define the operator< as a friend function, it works; if I define the operator< as a member function I get the error:
Error C2678 binary '<': no operator found which takes a left-hand >operand of type 'const _Ty' (or there is no acceptable conversion).
I do not understand why the version of operator< implemented as member function does not work/what should be changed about it.
I provide bellow a simplified example of the problem case:
class TestObj
{
private:
int m_a;
public:
TestObj(int a): m_a{a} {}
/* operator < as friend function works */
/*friend bool operator< (const TestObj& t1, const TestObj& t2)
{
return t1.m_a < t2.m_a;
}*/
/* operator < as member function does not work! */
bool operator< (const TestObj& t2)
{
return m_a < t2.m_a;
}
};
void testSetCompare()
{
std::set<TestObj> set1;
set1.insert(10);
set1.insert(20);
}
I do not understand why the version of operator< implemented as member function does not work/what should be changed about it.
You need to make the member function const. Because you declared it as 'non-const' the compiler cannot decide if yout operator willl change *this so your operator cannot be used in a when you have a const TEstObj& what is needed for insert
bool operator< (const TestObj& t2) const
{
return m_a < t2.m_a;
}
will do the job.
Edit: The "No acceptable converson" means that it cannot convert from const TestObj& to TestObj& because it would break the rules of const. (and your operator needs a TestObj&)

== operator overloading with struct

I'm trying to define an == operator within a struct, like this:
struct names {
string fname;
string lname;
bool operator==(names a, names b) {
return (a.fname == b.lname);
}
};
However, the compiler says:
..\src\trash.cpp:10:33: error: 'bool names::operator==(names, names)' must take exactly one argument
Why is this?
If you overload a binary operator as a member function, then it should only take one argument. The first operand is the object the operator is called on (i.e. *this); the second operand is the single function argument.
struct names {
//...
// better to pass by reference;
// make the function 'const' so it can be used on constant objects
bool operator==(names const & rhs) const {
return this->fname == rhs.lname;
}
};
Alternatively, you can overload it as a non-member function, with two arguments:
bool operator==(names const & lhs, names const & rhs) {
return lhs.fname == rhs.lname;
}
If this needed access to private members (which isn't the case in this example), then it would have to be a friend. You can define friends inside the class definition; in which case the code would look exactly the same as your example, only with friend in front of the function declaration.
(Of course, this isn't a sensible definition of equality since it's not symmetric. Many algorithms will break if you can have a == b but not b==a, as you can with this definition. lhs.fname == rhs.fname && lhs.lname == rhs.lname would make more sense.)
operator== is meant to compare two objects for equality. You have it appearing to compare the first and last names for different objects, presumably to catch duets like George Lazenby and Emma George.
I'd make it a member function of the class and use this for one of the objects:
bool operator== (const names &rhs) const {
return (this->fname == rhs.fname) && (this->lname == rhs.lname);
}
Do:
As member function:
struct names {
string fname;
string lname;
bool operator==(const names& rhs) const { /* Your code */ }
};
or as free function:
bool operator==(const names& lhs, const names& rhs) const { /* Your code */ }

Overloading operator in class

The object of the class 'Square_Matrix' stores an integer matrix.
Is this how I can check if two matrices are equivalent? I want to compare two 2d arrays by overloading '==' to check if every element is identical between the 2 matrices.
E.g: I need the following to work:
Square_Matrix a,b;
if (a == b) {return 1;}
Both a and b are dynamic 2d arrays.
However, I'm getting an error: unexpected initializer before 'operator'. How can I fix this? Other than that, is this how the syntax should look like?
//header file
bool operator==(Square_Matrix array1, Square_Matrix array2);
//.cpp file
bool Square_Matrix operator ==(Square_Matrix array1, Square_Matrix array2){
if (array1.size != array2.size){
return false;
}
for (int i = 0; i < array1.size; i++){
for (int j = 0; j < array1.size; j++){
if (array1[i][j] != array2[i][j]){
return false;
}
}
}
return true;
}
Most binary operators can be overloaded in either of two different ways. One is as a member function, the other as a global (free) function.
The member function version will take one parameter. An expression like: x == y will be interpreted as x.operator==(y).
The free function version takes two parameters. An expression like x == y is interpreted as operator==(x, y).
You need to decide which of those you're going to use, and define the number of parameters appropriately. Right now, it looks like you have a free function taking only one parameter, which would work for a unary operator, but not a binary operator.
When you overload as a free function, it's normally to provide symmetry. Specifically, a free function can convert either the left or the right operand to the correct type for the operator. A member function overload can only convert the right operand to the correct type for the operator.
The operator should be declared as
bool operator ==( const Square_Matrix &array2 ) const;
if it is a member of the class.
Or it could be declared as a friend function of the class as
friend bool operator ==( const Square_Matrix &array1, const Square_Matrix &array2 );
I suppose that the class has data member with name size that contains the size of the square matrix
bool Square_Matrix::operator ==( const Square_Matrix &array2 ) const
{
if ( size != array2.size ) return false;
for (int i = 0; i < size; i++ )
{
for ( int j = 0; j < size; j++ )
{
if ( mPoint[i][j] != array2.mPoint[i][j] ) return false;
}
}
return true;
}
EDIT: I removed some typos.
The problem with your code is that you need a ::
bool Square_Matrix operator ==(Square_Matrix array2){
becomes this:
bool Square_Matrix::operator ==(Square_Matrix array2){
The error "unexpected initializer before 'operator'" is because it didn't understand you were trying to use a class method.
Change Square_Matrix operator == to Square_Matrix::operator ==.
Also, don't you want to pass Square_Matrix by reference into your operator?
bool operator==(const Square_Matrix& that) const;
or
static bool operator==(const Square_Matrix& a,
const Square_Matrix& b);

overloaded < operator gives "no matching function for call" error when used in another class

I implemented a custom TimeStruct class, where I declare < operator as follows
bool operator<(const TimeStruct t2) const;
implementation is as follows.
bool TimeStruct::operator<(const TimeStruct t2) const
{
//do something, I don't include the actual implementation
return true;
}
Then I have another class X where this TimeStruct class is a member, let's call this member field Y. And I am using a vector, and I want to sort this vector on Y field of Class X. Therefore I will need to specify a method which might serve as a basis for the vector's sort method.
Therefore I declared an additional method in X to compare different X's.
bool compareX(const X& x1, const X& x2) const;
and the implementation is as follows:
bool X::compareX(const X& x1, const X& x2) const
{
return (x1.Y.operator<(x2.Y));
}
Unfortunately this code does not compile. I am receiving the following error.
No matching function call for TimeStruct::operator<(const TimeStruct&) const
candidates are : bool TimeStruct::operator<(TimeStruct&) const
I've been scratching my hair for the last hour, can anybody point out what I've been doing wrong.
You need to pass by const reference in your TimeStruct operator:
bool operator<(const TimeStruct& t2) const;
and, according to the error message, you have provided
bool operator<(TimeStruct&) const
There needs to be a const reference specifier in the operator declaration.
Furthermore, you may want to turn operator< from a member function into a friend function.
It's usually best practice.

Overriding an operator using const for both parameters in C++

I'm trying to create an overridden operator function using both const parameters, but I can't figure out how to do it. Here is a simple example:
class Number
{
Number()
{
value = 1;
};
inline Number operator + (const Number& n)
{
Number result;
result.value = value + n.value;
return result;
}
int value;
}
What I am trying to do here is pass in two arguments into the addition function that are both const and return the result without changing anything in the class:
const Number a = Number();
const Number b = Number();
Number c = a + b;
Is this possible and how would I go about doing this?
Thanks,
Dan
inline is understood in class declarations so you don't need to specify it.
Most idiomatically, you would make operator+ a non-member function declared outside the class definition, like this:
Number operator+( const Number& left, const Number& right );
You might need to make it a friend of the class if it needs access to Number's internals.
If you have to have it as a member function then you need to make the function itself const:
Number operator+( const Number& n ) const
{ // ...
For classes like Number, operator+ is typically implemented in terms of operator+= as usually you want all the usual operators to work as expected and operator+= is typically easier to implement and operator+ tends not to lose any efficiency over implementing it separately.
Inside the class:
Number& operator+=( const Number& n );
Outside the class:
Number operator+( const Number& left, const Number& right )
{
return Number( left ) += right;
}
or even:
Number operator+( Number left, const Number& right )
{
return left += right;
}
class Number
{
Number()
{
value = 1;
};
inline Number operator + (const Number& n) const
{
Number result;
result = value + n.value;
return result;
}
int value;
}
How about:
inline Number operator + (const Number& n) const
While I feel the previous answers are good enough, I believe some clarification is needed.
Operators come (usually) in two flavors
The first being the non-member functions, the second being the member function whose parameter is the "right operand" of the operation and which usually returns the current modified object.
For example, imagine there's an operator § for a class T. It could be written either as a non-member function:
T operator § (const T & lhs, const T & rhs)
{
T result ;
// do the lhs § rhs operation, and puts the result into "result"
return result ;
}
or as a member function:
T & T::operator § (const T & rhs)
{
// do the "this § rhs" operation, and puts the result into "this"
return *this ;
}
or even (very unusually) as another member function:
T T::operator § (const T & rhs) const
{
T result ;
// do the "this § rhs" operation, and puts the result into "result"
return result ;
}
Usually, you should prefer the non-member function, if only because you should not declare it friend. Thus, using non-member non-friend function enhance the encapsulation of your object.
Disclaimer: There are other flavors, but I'm limiting myself to arithmetic operators like +, *, /, -, etc. here, as well as "credible" operator prototypes.
Analyse your use of the operator
In the case of +:
Each operand needs to be constant because a = b + c must not change b, nor c.
You can accumulate +, like in a = b + c + d + e, so temporaries must exist.
T operator § (const T & lhs, const T & rhs)
{
T result ;
// do the lhs § rhs operation, and puts the result into "result"
return result ;
}
In the case of +=:
You know the left operand A (from A += B) will be modified.
You know the left operand A (from A += B) is its own result.
So you should use:
T & T::operator += (const T & rhs)
{
// do the "this § rhs" operation, and puts the result into "this"
return *this ;
}
As always, premature optimization is the root of all evil
I've seen this kind of code in production code so, it does happen:
T & operator + (const T & lhs, const T & rhs)
{
static T result ; // result is STATIC !!!!
// do the lhs + rhs operation, and puts the result into "result"
return result ;
}
The author hoped to economize one temporary. With this kind of code, writing a = b + c + d leads to interesting (and wrong) results.
^_^
Last but not least
I did write a list of operator overloading prototypes on this page. The page is still under construction, but its main use (easy to copy/paste working prototypes) can be quite useful...