Operator Overloading with template - c++

I am trying to modify the Add function to represent operator overloading.
#include <iostream>
using namespace std;
template <class T>
class cpair
{
public:
cpair(T x = 0, T y = 0) { A = x; B = y; }
void print()
{
cout << A << " " << B << endl;
}
T A, B;
};
template <class T>
void Add(cpair<T> A1, cpair<T> A2, cpair<T> &R)
{
R.A = A1.A + A2.A;
R.B = A1.B + A2.B;
}
int main()
{
cpair<int> A1(4, 5), A2(1, 3), result;
Add(A1, A2, result);
result.print();
return 0;
}
I am learning operator overloading, but I don't think I have implemented it correctly. The error I get is:
'operator= must be a member function'.
template <class T>
void operator=(const cpair<T> &A1, cpair<T> &A2, cpair<T> &R) {
R.A = A1.A + A2.A;
R.B = A1.B + A2.B;
}
int main()
{
cpair<int> A1(4, 5), A2(1, 3), result;
operator(A1, A2, result);
result.print();
}
How do you go about modifying the Add function to represent operator overloading and then call the function in Main? Thank you.

You're misunderstanding quite a lot it seems. First of all if you want to overload the addition operator it's the operator+ function you need to overload, not the assignment operator.
To fix this you should do e.g.
template <class T>
cpair<T> operator+(cpair<T> const& a, cpair<T> const& b)
{
return cpair<T>(a.A + b.A, a.B + b.B);
}
Secondly, if you overload an operator you can use it just like you would otherwise use it. For example, with e.g.
int a = 5, b = 7, r;
then you would do
r = a + b;
It's the same with your overloaded operators:
cpair<int> a(4, 5), b(1, 3), result;
result = a + b;
If you want to learn more I suggest you get a few good books to read.

template <class T>
class cpair {
public:
cpair& operator+=( cpair const& o )&{
A+=o.A;
B+=o.B;
return *this;
}
friend cpair operator+( cpair lhs, cpair const& rhs ){
lhs+=rhs;
return lhs;
}
//...
the above is the canonical way to override + on a template class.

Related

Overloading operator+ in a template class with 2 templates

I have the following templatе:
template <typename T1, typename T2>
class equationSolution {
public:
T1 a, b, c;
float d;
friend ostream& operator<< <T1, T2>(ostream& str, const equationSolution<T1, T2>& ov);
equationSolution<T1,T2>& operator+=(const equationSolution<T1, T2>& ov, const int& value);
equationSolution() : a(0), b(0), c(0) {}
equationSolution(T1 a1, T1 b1, T1 c1) : a(a1), b(b1), c(c1) {
a = a;
b = b;
c = c;
d = pow(b, 2) - 4 * a * c;
}
}
I managed to overload the output
template <typename T1, typename T2>
ostream& operator<<(ostream& str, const equationSolution<T1, T2>& ov)
{
str << "(" << ov.a << "," << ov.b << "," << ov.c << ")";
return str;
}
But with the operator += I have difficulties.
That's what I did:
friend equationSolution<T1, T2>& operator += (const equationSolution<T1, T2>& ov, const int& value) {
ov.a += value;
ov.b += value;
ov.c += value;
return ov;
}
But I have error:
binary "operator + =" has too many parameters
All assignment operator overloads (all of them) must be member functions, and as such they should take only one argument: The right-hand side of the operator.
That is, an expression like
foo += bar;
will be translated as
foo.operator+=(bar);
You declare the operator function as a member function, but using two arguments. Then you define (implement) the function as a non-member friend function, which is not allowed. The error you mention is from the declaration.
What you should do is something like
equationSolution& operator+=(const int& value)
{
// TODO: Implement the actual logic
return *this;
}

Scope operator in Operator Overloading

I'm not able to understand the scope operator in Operator overloading. There are examples when they are using it when they don't. When I'm supposed to write T::operator. Can I write just the operator still works fine or is it recommended to use::?
The example:
Prototype examples (for class T)
Inside class definition
T& T::operator +=(const T2& b){}
Can I write it like T& operator +=(const T2& b){}
Or should I always write it like T& T::operator +=(const T2& b){}
The operator += may be declared as a member function or member template of a class or class template and defined either within the class or class template or outside them.
If it is defined outside the class then the scope operator is required.
The operator may be also declared and defined as a stand-alone non-class function
Consider the following demonstrative program
#include <iostream>
struct A
{
int x = 0;
A & operator +=( char c )
{
x += c;
return *this;
}
};
struct B
{
int x = 0;
B & operator +=( char c );
};
B & B::operator +=( char c )
{
x += c;
return *this;
}
struct C
{
int x = 0;
};
C & operator +=( C & cls, char c )
{
cls.x += c;
return cls;
}
int main()
{
A a;
a += 'A';
std::cout << "a.x = " << a.x << '\n';
B b;
b += 'B';
std::cout << "b.x = " << b.x << '\n';
C c;
c += 'C';
std::cout << "c.x = " << c.x << '\n';
return 0;
}
Its output is
a.x = 65
b.x = 66
c.x = 67
The operator can be also declared as a template operator. For example
#include <iostream>
template <class T>
struct A
{
T x = T();
};
template <class T1, class T2>
T1 & operator +=( T1 &a, const T2 &x ) /* C++ 17 only requires requires( T1 t ) { t.x; }*/
{
a.x += x;
return a;
}
int main()
{
A<int> a;
std::cout << ( a += 10u ).x << '\n';
}
Again if the operator is a member function template and is defined outside its class then the scope resolution operator is required.
#include <iostream>
template <class T1>
struct A
{
T1 x = T1();
template <class T2>
A<T1> & operator +=( const T2 &x );
};
template <class T1>
template <class T2>
A<T1> & A<T1>::operator +=( const T2 &x )
{
this->x += x;
return *this;
}
int main()
{
A<int> a;
std::cout << ( a += 10u ).x << '\n';
}
Inside the class, you don't use the scope resolution operator :::
class T {
public:
// ...
T operator+=(const T2& b)
{
// ...
}
};
If you define the operator outside the class, then you use the scope resolution operator :: in the out of class definition. You still omit it in the declaration:
class T {
public:
// ...
T operator+=(const T2& b);
};
// in the implementation
T T::operator+=(const T2& b)
{
// ...
}
This has nothing to do with recommendation or good practice. Everything stated here is the only way that can work, the other ways are just not correct C++ code.

Inner class of a template class friend function

I have a templated class A with an inner class B. I want to have a friend == operator. However, the following code does not compile. It says, couldn't deduce template parameter ‘T’
#include <iostream>
template<typename T>
struct A
{
struct B
{
T b;
template<typename T2>
friend bool operator == (const typename A<T2>::B& b1, const typename A<T2>::B& b2);
};
B b;
};
template<typename T>
bool operator == (const typename A<T>::B& b1, const typename A<T>::B& b2)
{
return b1.b == b2.b;
}
int main() {
A<int>::B b1, b2;
b1.b = 3;
b2.b = 2;
std::cout << (b1 == b2) << std::endl;
return 0;
}
I have to have the friend version because the way one of the STL algorithms calls it results in == not found otherwise even if I have bool operator == (const B& b_) { return b == b_.b; }
What is the way to solve this?
It's a non-deduced context.
Ostensibly you could have a definition like
template<typename AB>
bool operator == (const AB& b1, const AB& b2)
{
return b1.b == b2.b;
}
but it's too broad as it catches all types. Yoiy can restrict it this way
template<typename AB>
auto operator == (const AB& b1, const AB& b2) ->
std::enable_if_t<std::is_same_v<AB, typename A<decltype(b1.b)>::B>, bool>
{
return b1.b == b2.b;
}
This worked for me.
#include <iostream>
template<typename T>
struct A
{
struct B
{
T b;
};
friend bool operator==(const typename A<T>::B &b1, const typename A<T>::B &b2)
{
return b1.b == b2.b;
}
B b;
};
int main() {
A<int>::B b1, b2;
b1.b = 3;
b2.b = 2;
std::cout << (b1 == b2) << std::endl;
return 0;
}

Overloading operator for default type in template

How can i overload operator in template class for every type expect- for example int and char.
Point<char> operator+ (Point<char> const& sec){
Point<char> tmp(x+2, y+3);
return tmp;
}
Point<int> operator+ (Point<int> const& sec){
Point<int> tmp(x+sec.x + 1, y+sec.y + 1);
return tmp;
}
Point<T> operator+ (Point<T> const& sec){
return Point<T>(x+sec.x, y+sec.y);
}
Something like this doesn't work. I can overload for specific types OR for T, but can't combine both.
You can explicitly specialize outside the class, like so (minimal example):
#include <iostream>
template<class T>
struct Point
{
Point operator+(Point rhs)
{
std::cout << "Generic\n";
return rhs;
}
};
template<>
Point<char> Point<char>::operator+(Point<char> rhs)
{
std::cout << "char\n";
return rhs;
}
template<>
Point<int> Point<int>::operator+(Point<int> rhs)
{
std::cout << "int\n";
return rhs;
}
int main()
{
Point<double> p;
Point<int> i;
Point<char> c;
p + p;
i + i;
c + c;
}
Live on Coliru
You can add an if statement like
if(std::is_same<T, int>::value) {...}
else if(std::is_same<T, char>::value) {...}
else {...}
Write this inside the code for Point operator+(){}.
I have never implemented this, but I think you can make it work.
I don't know if an operator can be overloaded the way you want, but you can try this.
To explicitly specialize a member you need its surrounding class template to be explicitly specialized as well. In your case you can use friends:
template <class T>
class Point {
public:
Point(T x, T y) : x(x), y(y) {}
private:
T x, y;
friend Point<char> operator+ (Point<char> const& a, Point<char> const& b);
friend Point<int> operator+ (Point<int> const& a, Point<int> const& b);
template<class T>
friend Point<T> operator+ (Point<T> const& a, Point<T> const& b);
template<class T>
friend Point<T*> operator+ (Point<T*> const& a, Point<T*> const& b);
};
Point<char> operator+ (Point<char> const& a, Point<char> const& b) {
std::cout << "overload for char" << std::endl;
return a;
}
Point<int> operator+ (Point<int> const& a, Point<int> const& b) {
std::cout << "overload for int" << std::endl;
return a;
}
template <class T>
Point<T> operator+ (Point<T> const& a, Point<T> const&) {
std::cout << "overload for other non-pointers type" << std::endl;
return a;
}
// you can even provide overload for pointers
template <class T>
Point<T*> operator+ (Point<T*> const& a, Point<T*> const&) {
std::cout << "overload for pointers" << std::endl;
return a;
}
int main() {
Point<int> p1(1,1);
p1 + p1;
Point<char> p2(1, 1);
p2 + p2;
Point<long long> p3(1, 1);
p3 + p3;
int i[2];
Point<int*> p4(i, i+1);
p4 + p4;
return 0;
}
overload for int
overload for char
overload for other non-pointer types
overload for pointers

Friend operator behavior (const vs non-const)

I have the following C++ code:
#include <iostream>
template <class T>
void assign(T& t1, T& t2) {
std::cout << "First method" << std::endl;
t1 = t2;
}
template <class T>
void assign(T& t1, const T& t2) {
std::cout << "Second method" << std::endl;
t1 = t2;
}
class A {
public:
A(int a) : _a(a) {};
private:
int _a;
friend A operator+(const A& l, const A& r);
};
A operator+(const A& l, const A& r) {
return A(l._a + r._a);
}
int main() {
A a = 1;
const A b = 2;
assign(a, a);
assign(a, b);
assign(a, a+b);
}
The output is:
First method
Second method
Second method
The output stays the same even if I comment out the the first 2 assigns in the main function.
Can someone please explain to me why the operator+ returns a const A?
The output is the same in both Linux Debian 64bit and Windows 7 64 bit.
It doesn't return a const A at all. It returns a temporary A, which may only bind to a const reference.