Binary Operator Overloading C++ - c++

I'm trying to overload the following operators to sort a string array using a Quick Sort or possibly Merge Sort algorithm. I'm have all my functions in a single class but I'm getting a "too many parameters for this operator function" error. Indeed, it will only accept one parameter. I looked up the problem and in a forum someone said that you can only use one parameter when overloading an operator inside a class. This doesn't make much sense to me. I'm trying to compare strings so I need the two parameters for the overloading. Am I supposed to overload the operators outside the class, and how would this work?
Here's my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class Preprocessing
{
public:
void readFile(string list[], int size);
void quickSort(int list[], int lowerBound, int upperBound);
void swapItem(int &a, int &b);
//These are the overloading functions I'm trying to implement
bool operator<=(string a, string b);
bool operator<(string a, string b);
bool operator>(string a, string b);
};
void Preprocessing::readFile(string list[], int size)
{
ifstream myFile;
myFile.open("words.txt");
for (int i = 0; i < size; i++)
{
myFile >> list[i];
}
myFile.close();
}
void Preprocessing::quickSort(int list[], int lowerBound, int upperBound)
{
int i, j, pivot;
i = lowerBound;
j = upperBound;
pivot = list[(i + j) / 2];
while (i <= j)
{
while(list[i] < pivot)
{
i = i + 1;
}
while (list[j] > pivot)
{
j = j - 1;
}
if (i <= j)
{
swapItem(list[i], list[j]);
i = i + 1;
j = j - 1;
}//end if
}//end outter while
if (lowerBound < j)
{
quickSort(list, lowerBound, j);
}
if (i < upperBound)
{
quickSort(list, i, upperBound);
}//end recursive if
}//end function
void Preprocessing::swapItem(int &a, int &b){
int tmp;
tmp = a;
a = b;
b = tmp;
}
bool Preprocessing::operator<=(string a, string b)
{
if (a.compare(b) > 0)
return false;
else if (a.compare(b) == 0)
return true;
else
return true;
}
bool Preprocessing::operator<(string a, string b)
{
if (a.compare(b) > 0)
return false;
else if (a.compare(b) == 0)
return true;
else
return true;
}
bool Preprocessing::operator>(string a, string b)
{
if (a.compare(b) > 0)
return false;
else if (a.compare(b) == 0)
return true;
else
return true;
}

The signatures for the operators are incorrect:
bool operator<=(string a, string b);
bool operator<(string a, string b);
bool operator>(string a, string b);
When you overload an operator - and you implement it as a member function, it should only accept one argument (the other thing to compare to)
If non-member function (i.e. friend), then you can provide two arguments, however it cannot match an exiting operator (there is one already defined for std::string), and typically should accept your class as lhs and rhs for testing.

An operator inside a class, whatever it is, has the special meaning of applying that operator to an instance of that class and optionally to parameters.
In your example the operator<= is supposed to compare an instance of the Preprocessing class with a string.
class Preprocessing
{
public:
bool operator<=(string a);
private:
string aStringField;
}
Typically you use this inside the operator method body to compare the instance with the parameter:
bool Preprocessing::operator<=(string a)
{
return this->aStringField.length() <= a.length();
}
And you call it with:
Preprocessing p;
if ( p <= "a string" )
// ...
Which is equivalent to:
Preprocessing p;
if ( p.operator<=("a string") )
// ...
If you want to provide an operator that doesn't need the "point syntax" to be called, then you're looking for friend operators that exist outside your class.
class Preprocessing
{
public:
friend ostream& operator<<(ostream&, const Preprocessing&);
private:
string aStringField;
}

It only takes one argument because the left hand side is passed as the this pointer.

To overload an operator, the operator needs to be a method of the lefthand operand. C++ chooses functions (and operators) based on the types of the arguments (operands). Within a class, the lefthand operand is an instance of the class, available as the this pointer, so only the righthand operand may be specified as an argument to the operator.
In your example, you could do this:
class Preprocessing {
public:
bool operator<=(string b);
};
which would define a <= operator for comparing Preprocessing objects to strings. If you need to overload string comparison operators, you need to modify the std::string class, which is beyond my knowledge.

Related

operator overloading opertator + cant convert from pointer to const

i have a sparse matrix that is created with two arrays and each array index have a linked list the non zero numbers are in there including the i and j indexs
the header
class MNode {
public:
double _data;
int _indexI, _indexJ; // the place of the node in the matrix
// clarification: _nextRow is a pointer to the next columns in the row
MNode* _nextRow, *_nextCol;
MNode(double data, int i, int j);
};
private:
string _type;
MNode** _rowHead, **_colHead;
int _rowSize, _colSize;
int _elemNum;
void setValue(int, int, double);
void removeElement(int, int);
void insertNode(MNode*);
bool IsExist(int, int);
void setElementByType(int i, int j, double data);
public:
// construct a 'rows X cols' matrix.
SMatrix(int rows, int cols,string type);
// set the (i,j) element to be 'data'
void setElement(int i, int j, double data);
// destroy this matrix.
~SMatrix();
double getElement(int, int);
friend std::ostream& operator<<(std::ostream& os, const SMatrix& mat);
SMatrix& operator = (const SMatrix& other);
SMatrix & operator+(const SMatrix & other) const;
};
the cpp here is the overloading + function i get an erorr
cannot convert this pointer to const SMatrix to Smatrix&
SMatrix &SMatrix::operator +(const SMatrix& other) const {
SMatrix temp(3, 3, "any") ;
if (other._rowSize == this->_rowSize&&other._colSize == this->_colSize&&other._type == this->_type) {
for (int j = 0; j < other._colSize; j++) {
for (int i = 0; i < other._rowSize; i++) {
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
}
}
}
return temp;
}
here is the contructor
SMatrix::SMatrix(int rows, int cols,string matType )
{
_type = matType;
_rowSize = rows;
_colSize = cols;
_elemNum = 0;
_rowHead = new MNode*[rows];
if (!_rowHead)
{
cout << "allocation error";
exit(1);
}
_colHead = new MNode*[cols];
if (!_colHead)
{
cout << "allocation error";
exit(1);
}
for (int i = 0; i < rows; i++)
{
_rowHead[i] = NULL;
}
for (int i = 0; i < cols; i++)
{
_colHead[i] = NULL;
}
}
iam not sure what i need to do the signature of the function is given and cant be chanbged any idea?
You've declared other to be a reference to const:
SMatrix & operator+(const SMatrix & other) const;
^^^^^
You call the member function getElement on that reference:
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
^^^^^^^^^^^^^^^^
You've declared getElement to be non-const:
double getElement(int, int);
^
You may only call const member functions on const references.
the signature of the function is given and cant be chanbged any idea?
If the signature of getElement can't be changed, then you've been dealt a badly written signature. There should be no good reason why a getter couldn't be const. That said, since you're within the class, you can access all members directly without using a getter.
There's another bug. You've declared operator+ to return a reference.
SMatrix &SMatrix::operator +(const SMatrix& other) const
^
But you return a local automatic variable temp:
SMatrix temp(3, 3, "any") ;
// ...
return temp;
Automatic variables are destroyed at the end of the function. Therefore the returned reference will always be dangling and any use of it would have undefined behaviour.
the signature of the function is given and cant be chanbged any idea?
If the signature of operator+ can't be changed, then you've been dealt a badly written signature. The function really should return by value. There's no sensible solution that could return a reference. Using a static local would technically work, but that has some limitations on usage that aren't apparent from the interface.

Overloading operator+ in class

Let's say I have a class Number
class Number
{
public:
int numb;
Number (int g)
{
numb = g;
}
int operator+(int h)
{
return this->numb+h;
}
};
And when I try to use my overloaded operator
cout << 3 + s; // doesn't work
cout << s + 3;
I understand why it doesn't work, but I don't know how to make it work for 3 + s
Of course, I can write operator+ with 2 arguments outside the class, but I want to have my operator overloaded in the class.
I've googled it, but didn't find any solution.
Easiest way to go: write another overload outside of your class
class Number
{
public:
int numb;
Number (int g)
{
numb = g;
}
int operator+(int h)
{
return this->numb+h;
}
};
int operator+(int h, Number& n)
{
return n.numb+h;
}
int main()
{
int s = 42;
std::cout << 3 + s;
std::cout << s + 3;
}
Live Example
This also works if your data is private (but make sure the outside function has access to those members)
class Number
{
int numb;
public:
Number (int g)
{
numb = g;
}
int operator+(int h)
{
return this->numb+h;
}
friend int operator+(int, Number&);
};
int operator+(int h, Number& n)
{
return n.numb+h;
}
Of course, I can write operator+ with 2 arguments outside the class, but I want to have my operator overloaded in the class.
This is like saying "Of course I could hammer in my nail with a hammer, but I want to use a screwdriver..."
Some other solutions suggested using both a member and a non-member, but that is redundant: if you add the non-member then you no longer need the member!
The proper way to overload operator+ is to use the non-member:
Number operator+(Number a, Number b)
{
return a.numb + b.numb;
}
Another way to write this is to use operator+= as a helper (then your class will support += too):
Number operator+(Number a, Number b)
{
return a += b;
}
with member function:
Number &operator+=(Number b)
{
numb += b.numb;
return *this;
}
You could either make operator+ return Number or int, your choice.
Just write an operator outside the class that calls the one in your class!
template<typename T> T operator+(T a, Number& n)
{
return n+a;
}

Why does my operator overloading handle left versus right objects?

I had a question on operator overloading. Below is my the example code. If you can read through it and my question is below.
//class definition
class example
{
private:
int a ; // Defined in FeetInches.cpp
public:
void seta(int f)
{
a = f;
}
example operator + (const example &); // Overloaded +
int geta()
{
return a;
}
};
example example::operator + (const example &right)
{
example temp;
temp.a = a + right.a;
return temp;
}
//main
#include "header" //this is the class definition above
#include <iostream>
using namespace std;
int main()
{
example r;
r.seta(1);
example s;
s.seta(1);
example t;
t = r + s;
t = r + 1; //if included it won't compile
t = 1 + r; //if included it won't compile
int x = t.geta();
cout << x;
cin.get();
return 0;
}
I understand that when you attempt to add to objects together using operator overloading they should be the same.
Here is the question:
I recently saw when the object was on one side of the operator it compiled but when it was on the other it didn't. Such as:
t = r + 1; it compiled.
t = 1 + r; it didn't.
(Also I know in my example it doesn't work either way but was just easier to frame question with code.)
How does operator overloading compile when the object is on one side of the operator but not compile when it is on the other.
Thanks
If you rewrite the offending statement verbosely, it looks like:
t.operator=(1.operator+(r));
Which doesn't make a lot of sense and confuses the compiler.
Being confused, it can either convert the number 1 to an instance of example or convert the variable r to an integer. Unfortunately, you don't supply enough information in your class to do either.
If you provide a constructor for your class that takes an integer, things may come out less confusing:
class example
{
public:
example(int new_value) : a(new_value)
{ ; }
};
Now you have provided the compiler with a method convert integers into examples.
Another alternative is to provide a casting or conversion operator:
class example
{
public:
int operator int (const example& e)
{
return e.a;
}
};
There are other alternatives, such as creating an addition method that takes an integer.
Edit 1:
If you are designing a units class beware of constants. You have no idea what unit the constant is in, such as feet or inches. The compiler won't be able to help, since numerical constants don't have units associated with them.
It's really simple, when you overloading operator you can do it in two ways:
First is like you do it. You inserted overloaded operator for your class in it. This way the left argument must be the object of this class. Why? Because when you call this operator you can do it as call of every function in your class. You can't do it other way, because you can't call this function by other type.
Second, you made overloaded operator as friend to your class.
In your class you put this line:
friend example& operator + (const example &left, const example &right);
And after your class definition you put this:
example& operator + (const example &left, const example &right){...}
So if you want to add integer or other types you must just modify your operator to add it like this:
example& operator + (const example &left, const int right){...}
or this:
example& operator + (const int left, const example &right){...}
Choose one or both if you want to add int from left or rigth side of the opearator.
t = r + 1; means t = r.operator+(1); if r defines a matching operator+() method, otherwise it means t = operator+(r, 1); instead. It does not compile because you did not define any + operator that takes an example on the left and an int on the right, eg:
// as a class method:
class example
{
...
public:
...
example operator + (int right) const;
};
example example::operator + (int right) const
{
example temp;
temp.seta(a + right);
return temp;
}
Or:
// as a global operator:
class example
{
...
public:
...
friend example operator + (const example& left, int right);
};
example operator + (const example& left, int right)
{
example temp;
temp.seta(left.a + right);
return temp;
}
If you had defined a contructor that takes an int as input, the compiler could have created a temp example when you pass an int value to the example::operator+(const example&) method, eg:
class example
{
...
public:
example (int f);
...
example operator + (const example& right);
};
example::example::(int f)
: a(f)
{
}
example example::operator + (const example& right)
{
example temp;
temp.a = a + right.a;
return temp;
}
Likewise, t = 1 + r; means t = operator+(1, r); (since 1 is not a class type). It does not compile because you did not define a global + operator that takes an int on the left and an example on the right:
class example
{
...
public:
...
friend example operator + (int left, const example& right);
};
example operator + (int left, const example& right)
{
example temp;
temp.a = left + right.a;
return temp;
}

Overloading operators for class with cast operator and single-argument constructor

I have such code
class Number
{
int m_value;
public :
Number(const int value) :
m_value(value)
{
}
operator const int() const
{
return m_value;
}
int GetValue() const
{
return m_value;
}
};
bool operator==(const Number& left, const Number& right)
{
return left.GetValue() == right.GetValue();
}
class Integer
{
int m_value;
public :
Integer(const int value) :
m_value(value)
{
}
operator const int() const
{
return m_value;
}
bool operator==(const Integer& right) const
{
return m_value == right.m_value;
}
bool operator==(const int right) const
{
return m_value == right;
}
int GetValue() const
{
return m_value;
}
};
bool operator==(const int left, const Integer& right)
{
return left == right.GetValue();
}
int main()
{
Number n1 = 1;
Number n2 = 1;
int x3 = 1;
n1 == n2;
n1 == x3; // error C2666: 'operator ==' : 3 overloads have similar conversions
x3 == n1; // error C2666: 'operator ==' : 2 overloads have similar conversions
Integer i4 = 1;
Integer i5 = 1;
i4 == i5;
i4 == x3;
x3 == i4;
return 0;
}
For class Number I have two errors as shown in the code above. For class Integer everything is OK. The problem is, I want to keep in resulting class single-parameter constructor, cast operator and equality operations (MyClass == int, int == MyClass, MyClass == MyClass), but I want to implement only one version of operator== as in class Number. I don't see any way to do this. Is that even possible or I must have all three implementations as in class Integer? I know why I get these errors I just don't like the solution I have.
In class Number you define a conversion operator to int and your constructor allows converting an int to a Number. Therefore, when comparing a Number n and an int x for equality, ambiguity arises: should the compiler invoke the built-in operator == for ints and convert n to an int, or should it rather pick your operator and convert x to a Number? Both conversions are equally good, and it can't choose one.
So yes you have to define three versions, or add a template operator which can perfectly match the type of all arguments and forward to your operator explicitly, like this one (but you most likely want to guard it with some enable_if to limit its applicability only to the appropriate T and U):
template<typename T, typename U> // beware: this will match anything. to be constrained
bool operator == (T n, U const& u)
{
return (Number(n) == Number(u));
}
You can define only one operator== as member function:
bool operator==(const int& right) const
{
std::cout << "custom\n";
return this->GetValue() == right;
}
Then,
n1==n2: n2 will be converted to int and custom operator will be used.
n1 == n3: custom operator will be used
n3==n1: built-in operator will be used
Note, that you want your operator== be const to be able to compare constant Numbers
In C++11 you can make operator int explicit.
Another approach would be to use SFINAE to have a template == that works for one or more Number args, but that is using a bazooka to kill an ant.

Templated operator overload trick

Is there a way to by using some metaprogramming trick make situation like this works:
int* get();//this fnc returns pointer to int OR nullptr
int k = 1;
//this is the operator which is supposed to compare value and pointer
template<class T>
bool operator!=(const T& left, const T* right)
{
if (right)
{
return left != *right;
}
else
{
return false;
}
}
//And this is the code fragment which interests me most
if (k != get())
{
///
}
The crux is that I would like NOT TO change this line k != get() and yet for some reason my operator!= seems not to work. What's the problem?
You can only overload operators with at least one user-defined type as an argument. Neither int nor int* are user-defined types.
You can't overload operators for builtin types.
As already mentioned in other answers that you cannot have operator != for non userdefined types like int, char and so on.
One option is to wrap int inside your user defined struct and achieve the goal.
struct Int
{
int i;
// define all the necessary operators/constructor who deal with 'int'
Int(int x) : i(x) {}
bool operator != (const int* right)
{
return (right)? (i != *right) : false;
}
};
Now declare
Int k = 1;