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.
Related
I've written a class Number that contains only one attribute: T value. I'm currently learning about templates, so T is the data type. What I want to achieve is doing the following sort of computation.
Number<int>(2) + Number<double>(1.2)
What I have so far can do a operation, but it fails when there are two different datatypes. So far I've written this:
//class template
template<class T>
class Number
{
public:
T value;
Number(T num1)
{
value = num1;
}
Number<T> operator + ( const Number<T> &other) const
{
return Number<decltype(value+other.value)> (value+other.value);
}
};
It only does the arithmic operation when the datatypes are the same:
Questions:
Why does the program only work with the same datatypes?
This can I answer for a part by myself. I use the line:
Number<T> operator + ( const Number<T> &other) const
So if the left handside is of type int. Every T becomes an int. I don't know how I need to change it without getting an error.
What do I need to fix in order to do computations with different
datatypes?
Edit:
A constraint is that the template may contain only one type argument
Besides declaring a friend operator+ with two template parameters as suggested, you can also place a secondary template for the member function operator+, which allows you to do casting plus.
template<typename T>
class Number
{
public:
T value;
Number(const T&num1)
{
value = num1;
}
template <typename X> auto operator + ( const Number<X> &other) const
{
auto c = this->value + other.value;
return Number<decltype(c)> ( c );
}
};
#include <iostream>
int main()
{
Number<int> n{2};
Number<double> a{3.4};
std::cout << (a+n).value << std::endl;
}
Or, you may use a friend function (I think that this is more symbolic consistent.)
template<typename T>
class Number
{
public:
T value;
Number(T num1)
{
value = num1;
}
Number& operator +=( const Number<T> &other)
{
this->value += other.value;
return *this;
}
};
template <typename T1,typename T2> auto operator+(const Number<T1>&a, const Number<T2>&b)
{
auto c = a.value + b.value;
return Number<decltype(c)>( c );
}
#include <iostream>
#include <type_traits>
template <typename T>
struct Number {
Number(T _value = T(0)) : value(_value) {}
template <typename S>
Number(const Number<S>& n) : value(n.value) {}
T value;
template <typename S>
friend Number<S> operator+(const Number<S>& a, const Number<S>& b);
};
template <typename S>
Number<S> operator+(const Number<S>& a, const Number<S>& b) {
return Number<S>{a.value + b.value};
}
int main() {
std::cout << operator+<typename std::common_type<int, double>::type>(Number<int>{1}, Number<double>{1.2}).value << std::endl;
return 0;
}
this is a c++11 implementation. operator+ contains exactly one argument. I hope this is what you want.
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;
}
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.
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
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.