How to properly overload '+' operator for a struct - c++

I'd like to overload the '+' operator for A struct but I'm getting compiler warning
Here's my attempt :
struct wektor{
int x;
int y=0;
int norm(){
return x*x+y*y;
}
};
wektor& operator +(wektor &a,wektor &b){
wektor c;
c.x=a.x+b.x; // 12 line - warning here
c.y=a.y+b.y;
return c;
};
Compiler warning:
[Warning] non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default] in 12 line

The warning is telling you about the line:
int y=0;
You can't have an initialiser on a non-static non-const member prior to C++11. If you want to initialise y to 0 then you have to provide a constructor for wektor with a member initialization list.
Nonetheless, your operator+ parameters should be of type const wektor&. It should also return by value, because at the moment you're returning a reference to a local object that will be destroyed at the end of the function, and that is bad. It should look like this:
wektor operator +(const wektor &a, const wektor &b){
wektor c;
c.x=a.x+b.x; // 12 line - warning here
c.y=a.y+b.y;
return c;
};

First of all, binary operator+ should return a new value, not a reference. And if implemented in terms of references as input, these should be const:
wektor operator +(const wektor &a, const wektor &b);
Second, the warning is about this initialization:
struct wektor{
int x;
int y=0; // HERE! C++11 only
int norm(){
return x*x+y*y;
}
};
You can only do this in C++11. You could use a constructor in C++03.
struct wektor{
wector() : y() {} // zero-initializes y
int x;
int y;
int norm(){ return x*x+y*y;}
};
Going back to the operator+, I would implement an member operator+=, and then use it in a non-member operator+:
wektor operator +(wektor a, const wektor &b)
{
return a+= b;
}
Alternatively, give wector a two parameter constructor for x and y:
wector(int x, int y) : x(x), y(y) {}
ant then
wektor operator + (const wektor& a, const wektor &b)
{
return wector(a.x + b.x, a.y + b.y);
}

Not like that. The signature should be
wektor operator +(const wektor &a, const wektor &b)
I.e. don't return by reference from the + operator, and, even more importantly, don't return a temporary by reference.

That's a warning that you're using a feature from C++11, which isn't available in previous C++ standards.
When you know that what you've programed works the way you think, you can
get rid of this error by doing:
If you're using CodeBlocks:
Right-Click "Build Options..."
Select the "Other Options" tab
Add "-std=gnu++11"
If you're using the command line:
Add "-std=gnu++11" to the command arg's.

Related

How can I override the << operator for a class without it being in its namespace? [duplicate]

Is there a difference between defining a global operator that takes two references for a class and defining a member operator that takes only the right operand?
Global:
class X
{
public:
int value;
};
bool operator==(X& left, X& right)
{
return left.value == right.value;
};
Member:
class X
{
int value;
bool operator==( X& right)
{
return value == right.value;
};
}
One reason to use non-member operators (typically declared as friends) is because the left-hand side is the one that does the operation. Obj::operator+ is fine for:
obj + 2
but for:
2 + obj
it won't work. For this, you need something like:
class Obj
{
friend Obj operator+(const Obj& lhs, int i);
friend Obj operator+(int i, const Obj& rhs);
};
Obj operator+(const Obj& lhs, int i) { ... }
Obj operator+(int i, const Obj& rhs) { ... }
Your smartest option is to make it a friend function.
As JaredPar mentions, the global implementation cannot access protected and private class members, but there's a problem with the member function too.
C++ will allow implicit conversions of function parameters, but not an implicit conversion of this.
If types exist that can be converted to your X class:
class Y
{
public:
operator X(); // Y objects may be converted to X
};
X x1, x2;
Y y1, y2;
Only some of the following expressions will compile with a member function.
x1 == x2; // Compiles with both implementations
x1 == y1; // Compiles with both implementations
y1 == x1; // ERROR! Member function can't convert this to type X
y1 == y2; // ERROR! Member function can't convert this to type X
The solution, to get the best of both worlds, is to implement this as a friend:
class X
{
int value;
public:
friend bool operator==( X& left, X& right )
{
return left.value == right.value;
};
};
To sum up to the answer by Codebender:
Member operators are not symmetric. The compiler cannot perform the same number of operations with the left and right hand side operators.
struct Example
{
Example( int value = 0 ) : value( value ) {}
int value;
Example operator+( Example const & rhs ); // option 1
};
Example operator+( Example const & lhs, Example const & rhs ); // option 2
int main()
{
Example a( 10 );
Example b = 10 + a;
}
In the code above will fail to compile if the operator is a member function while it will work as expected if the operator is a free function.
In general a common pattern is implementing the operators that must be member functions as members and the rest as free functions that delegate on the member operators:
class X
{
public:
X& operator+=( X const & rhs );
};
X operator+( X lhs, X const & rhs )
{
lhs += rhs; // lhs was passed by value so it is a copy
return lhs;
}
There is at least one difference. A member operator is subject to access modifiers and can be public, protected or private. A global member variable is not subject to access modifier restrictions.
This is particularly helpful when you want to disable certain operators like assignment
class Foo {
...
private:
Foo& operator=(const Foo&);
};
You could achieve the same effect by having a declared only global operator. But it would result in a link error vs. a compile error (nipick: yes it would result in a link error within Foo)
Here's a real example where the difference isn't obvious:
class Base
{
public:
bool operator==( const Base& other ) const
{
return true;
}
};
class Derived : public Base
{
public:
bool operator==( const Derived& other ) const
{
return true;
}
};
Base() == Derived(); // works
Derived() == Base(); // error
This is because the first form uses equality operator from base class, which can convert its right hand side to Base. But the derived class equality operator can't do the opposite, hence the error.
If the operator for the base class was declared as a global function instead, both examples would work (not having an equality operator in derived class would also fix the issue, but sometimes it is needed).

overload greater than operator with or without friend

Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;

Operator needs zero or one argument

I have multiple errors that say either "<snippet of code> needs zero or one argument" or "<snippet of code> needs exactly one argument." For the sake of simplicity I will only post one of these sections of code from my file.h and my file.cc. I don't believe there is anything wrong with my main.cc. Also, the function must be a friend function of the class my_int, so I cannot make it a different type of function or simply use accessor functions. Any help anyone could provide would be most appreciated. Thank you!
file.cc
(friend function of my_int class):
my_int my_int::operator+(const my_int& num1, const my_int& num2) {
my_int temp;
temp = num1 + num2;
return(temp);
}
file.h
(inside a class named my_int)
friend my_int operator+(const my_int& num1, const my_int& num2);
friend my_int operator+(const my_int& num1, const my_int& num2);
means 'declare a free function which takes 2 parameters. Make it a friend so it can see my private members'
my_int my_int::operator+(const my_int& num1, const my_int& num2) {
means 'define the (illegal) member function operator+ which takes total 3 arguments.
EDIT: by request, adding some more info.
There are a number of "correct" ways to implement operators on your classes. The 'best practice' way is to implement all binary operators as free functions (operator+ as a free function is declared with 2 parameters). Operator+ should be implemented where possible in terms of operator+= (a unary operator, therefore define it in the class). It's best practice because it allows you to write overloads of operator+ that take different objects as arguments. For example:
struct X {
explicit X(int val) : _val (val) {}
// getter
int value() const { return _val; }
// this helper += operator eases our journey later on
X& operator+=(int delta) {
_val += delta;
return *this;
}
X& operator+=(const X& r) {
_value += r.value();
return *this;
}
private:
int _val;
}
// implements X + X
X operator+(X l, const X& r)
{
return l += r;
}
// implements X + int
X operator+(X l, int r)
{
return l += r;
}
// implement int + X (returns an X)
X operator+(int l, X r) {
return r += l;
return r;
}
// later, someone else defines a Y and wants it to be addable with X, returning a Z
struct Y {
vector<int> get_numbers() const;
}
struct Z {
Z(vector<int> v);
}
// implement Z = X + Y;
Z operator+(const X& l, const Y& r) {
auto v = r.get_numbers(); // vector<int> instead of auto for c++03
v.push_back(l.value());
return Z { std::move(v) }; // c++11
// return Z(v); // c++03
}
// also implement Z = Y + X
Z operator+(const Y&l , const X&r) {
auto v = l.get_numbers();
v.push_back(r.value());
return Z { std::move(v) };
}
Note that it's possible to declare the free-function forms of binary operators as friends:
struct X {
// this is a free function - not a class memeber, but it can see X::_value
friend X operator+(X, const X&);
private:
int _value;
};
// implementation
X operator+(X l, const X& r) {
l._value += r._value;
return l;
}
but I would argue that this style is less preferable to writing truly unbound free binary operators that are implemented in terms of unary operators (above).
It's also possible to implement binary operators as member functions - in which case they are declared and defined with one parameter (the other being implied as this):
struct X {
X operator+(X r);
private:
int _value;
};
X X::operator+(const X& r) {
// l is implied as *this
return X { _value + r._value };
}
but this is a mistake because while it allows the overload of (X + int), it does not allow overloading (int + X), for which you'd need a free function anyway.
This method:
my_int my_int::operator+(const my_int& num1, const my_int& num2);
is a member function. A member function operator implicitly takes as its left parameter the object pointed to by this (which will be a my_int object). That means that your overload's parameter declaration can't contain more than one object. Change your signature to:
my_int my_int::operator+(const my_int& num2);
Now what was num1 previously is now *this.
The operator + can be used in two kinds of expressions:
unary "plus" expression: +a
binary "plus" expression: a + b
The operator is overloadable for both kinds of expressions. Each overload must be either unary or binary. If the overload is a member function, then the implicit instance argument provides the first operand.
So you have these options:
Free functions:
R operator+(T a) is eligible for +a when a is convertible to T.
S operator+(T lhs, U rhs); is eligble for a + b when a is convertible to T and b to U.
Member functions:
struct Foo
{
R operator+(); // #1
S operator+(T rhs); // #2
} x;
Overload #1 is eligible for +x.
Overload #2 is eligible for x + b when b is convertible to U.

Is it possible to overload the ostream operator for arithmetic expressions?

Is it possible to create an overload for the ostream operator that does an arithmetic operation (addition for example) and then streams out the result? The standard ostream overload that can be found all over the web can only stream from a single variable. I need something that does the following:
std::cout << x+y << std::endl;
or even more complex expressions like:
std::cout << x*y+(3*z)^2 << std::endl;
where x, y, and z are instances of a simple custom-made struct where arithmetic operations are already defined (overloaded).
EDIT:
Here is my code:
struct scalar //complex scalar data structure
{
friend scalar operator^(const scalar&, int); //integer power operator overload
friend scalar exp(const scalar&); //exponential power function
std::ostream& operator<<(std::ostream&, const scalar&)
protected:
double re;
double im;
public:
double real() {return re;} //returns the real part
double imag() {return im;} //returns the imaginary part
scalar(double _re, double _im) {re=_re;im=_im;} //constructor 1
scalar(double _re) {re=_re;im=0.0;} //constructor 2
scalar(const scalar& s): re(s.re), im(s.im) {} //copy constructor
scalar& operator=(const scalar& rhs) //assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=rhs.re; //sets real parts equal
im=rhs.im; //sets imaginary parts equal
return *this;
}
scalar& operator+=(const scalar& rhs) //compound addition-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re+rhs.re; //adds real parts
im=im+rhs.im; //adds imaginary parts
return *this;
}
scalar& operator*=(const scalar& rhs) //compound multiplication-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
re=x1*x2-y1*y2; //multiplies real parts
im=x1*y2+x2*y1; //multiplies imaginary parts
return *this;
}
scalar& operator-=(const scalar& rhs) //compound subtraction-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
re=re-rhs.re; //adds real parts
im=im-rhs.im; //adds imaginary parts
return *this;
}
scalar& operator/=(const scalar& rhs) //compound division-assignment operator overload
{
if (&rhs==this) return *this; //checks for self-assignment
double x1=re; double x2=rhs.re; double y1=im; double y2=rhs.im;
double n;
n =pow(x2,2)+pow(y2,2);
if (n==0) throw(1);
re=(x1*x2+y1*y2)/n; //multiplies real parts
im=(x2*y1-x1*y2)/n; //multiplies imaginary parts
return *this;
}
const scalar operator+(const scalar& b) //addition operator overload
{
scalar c = *this;
c+=b;
return c;
}
const scalar operator*(const scalar& b) //addition operator overload
{
scalar c = *this;
c*=b;
return c;
}
const scalar operator-(const scalar& b) //addition operator overload
{
scalar c = *this;
c-=b;
return c;
}
const scalar operator/(const scalar& b) //addition operator overload
{
scalar c = *this;
c/=b;
return c;
}
};
scalar i(0.0,1.0);
scalar j(0.0,1.0);
std::ostream& operator<<(std::ostream& out, const scalar& s)
{
out << s.re << '+' << s.im << 'i';
return out;
}
scalar operator^(scalar a, int b) //integer power operator overload
{
double x=a.real(); double y=a.imag();
if (x==0) throw(1);
int r=sqrt(pow(x,2)+pow(y,2));
int arg=atan2(y,x);
scalar c(r*cos(arg),r*sin(arg));
return c;
}
scalar exp(const scalar& s) //exponential power function
{
double x=s.re; double y=s.im;
scalar c(exp(x)*cos(y),exp(x)*sin(y));
return c;
}
Here is my main function:
int main()
{
scalar x(3,4);
scalar y=2;
cout << x*y << endl;
return 0;
}
This is is the output it is supposed to give:
6+8i
And this is the errors it gives instead:
In function 'std::ostream& operator<<(std::ostream&, const scalar&)':|
error: passing 'const scalar' as 'this' argument of 'double scalar::real()'
discards qualifiers|
And if I remove the const as the compiler says, I will get the following error:
error: no match for 'operator<<' in 'std::cout << scalar::operator*(const scalar&)
(((const scalar&)((const scalar*)(& y))))'|
The << operator can't handle the full expression - and why should it?
You need to implement the separate operators (operator+, operator*, ...) for your struct, which take your structs as parameters, do the corresponding operation on it, and return another of your structs. And only then define a operator<< taking a single one of your structs.
How would you even think of passing in such a complex structure to the operator<<, let alone parse it in there? Implement the separate operators, and leave the parsing to the compiler.
e.g. for a simple struct only encapsulating an int, doing that with + operation would look like this:
struct mystruct
{
int value;
};
then define:
mystruct const operator+(mystruct const & a, mystruct const & b)
{
mystruct result;
result.value = a.value + b.value;
return result;
}
and
std::ostream & operator<<(std::ostream& out, mystruct const & a)
{
out << a.value;
return out;
}
then you can do:
mystruct a, b;
a.value = 1;
b.value = 2;
std::cout << a+b;
Edit: With your updated code, there's exactly one problem:
std::ostream& operator<<(std::ostream&, const scalar&)
should be
friend std::ostream& operator<<(std::ostream&, const scalar&);
i.e. you're missing friend and an ;
Though the error you show suggests some different problem (which jrok's answer would have a solution for) - that doesn't seem to result from compiling the code you show! So please get the shown code and error message in sync.
The error is because functions scalar::real and scalar::imag are not const - you can only call const member functions when you've got a reference to a constant scalar.
double real() const {return re;}
double imag() const {return im;}
Why don't you just write std::cout << (x+y) << std::endl;
and be done?
As long as your overloaded operator takes its argument by value:
ostream& operator<<(ostream&, Thing)
or constant reference:
ostream& operator<<(ostream&, const Thing&)
you can use it for any expression with type Thing.
You should put parentheses around complex expressions, to avoid surprises from operator precedence; in particular, the second expression involving ^ won't be parsed as you expect.
You'll only be restricted to a single variable (or, more accurately, an lvalue expression) if the operator requires a non-constant reference; so don't do that.
UPDATE Now we've seen the code, the main issue is the in-class definition of operator<< as a member function; it can't be a member. Perhaps you want it to be a friend, so it can access im and re; or perhaps you should remove the declaration (making it a non-member, non-friend), and just use the public interface. If you do that, you'll need to add const to real() and imag(), so they can be called on a const object. You should do that anyway.
(Looking at the reported error, it seems you've already changed it to use the public interface, but haven't declared the necessary functions const).

difference between global operator and member operator

Is there a difference between defining a global operator that takes two references for a class and defining a member operator that takes only the right operand?
Global:
class X
{
public:
int value;
};
bool operator==(X& left, X& right)
{
return left.value == right.value;
};
Member:
class X
{
int value;
bool operator==( X& right)
{
return value == right.value;
};
}
One reason to use non-member operators (typically declared as friends) is because the left-hand side is the one that does the operation. Obj::operator+ is fine for:
obj + 2
but for:
2 + obj
it won't work. For this, you need something like:
class Obj
{
friend Obj operator+(const Obj& lhs, int i);
friend Obj operator+(int i, const Obj& rhs);
};
Obj operator+(const Obj& lhs, int i) { ... }
Obj operator+(int i, const Obj& rhs) { ... }
Your smartest option is to make it a friend function.
As JaredPar mentions, the global implementation cannot access protected and private class members, but there's a problem with the member function too.
C++ will allow implicit conversions of function parameters, but not an implicit conversion of this.
If types exist that can be converted to your X class:
class Y
{
public:
operator X(); // Y objects may be converted to X
};
X x1, x2;
Y y1, y2;
Only some of the following expressions will compile with a member function.
x1 == x2; // Compiles with both implementations
x1 == y1; // Compiles with both implementations
y1 == x1; // ERROR! Member function can't convert this to type X
y1 == y2; // ERROR! Member function can't convert this to type X
The solution, to get the best of both worlds, is to implement this as a friend:
class X
{
int value;
public:
friend bool operator==( X& left, X& right )
{
return left.value == right.value;
};
};
To sum up to the answer by Codebender:
Member operators are not symmetric. The compiler cannot perform the same number of operations with the left and right hand side operators.
struct Example
{
Example( int value = 0 ) : value( value ) {}
int value;
Example operator+( Example const & rhs ); // option 1
};
Example operator+( Example const & lhs, Example const & rhs ); // option 2
int main()
{
Example a( 10 );
Example b = 10 + a;
}
In the code above will fail to compile if the operator is a member function while it will work as expected if the operator is a free function.
In general a common pattern is implementing the operators that must be member functions as members and the rest as free functions that delegate on the member operators:
class X
{
public:
X& operator+=( X const & rhs );
};
X operator+( X lhs, X const & rhs )
{
lhs += rhs; // lhs was passed by value so it is a copy
return lhs;
}
There is at least one difference. A member operator is subject to access modifiers and can be public, protected or private. A global member variable is not subject to access modifier restrictions.
This is particularly helpful when you want to disable certain operators like assignment
class Foo {
...
private:
Foo& operator=(const Foo&);
};
You could achieve the same effect by having a declared only global operator. But it would result in a link error vs. a compile error (nipick: yes it would result in a link error within Foo)
Here's a real example where the difference isn't obvious:
class Base
{
public:
bool operator==( const Base& other ) const
{
return true;
}
};
class Derived : public Base
{
public:
bool operator==( const Derived& other ) const
{
return true;
}
};
Base() == Derived(); // works
Derived() == Base(); // error
This is because the first form uses equality operator from base class, which can convert its right hand side to Base. But the derived class equality operator can't do the opposite, hence the error.
If the operator for the base class was declared as a global function instead, both examples would work (not having an equality operator in derived class would also fix the issue, but sometimes it is needed).