Overriding +/-/*/% by integer and the -Weffc++ flag - c++

I have a class called Coord...it has instance data x, y. I want to override the * operator such that the * operator can be used to multiply the Coord by an integer or double! This is the solution I put up:
Coord& Coord::operator*(int n)
{
this->x = this->x*n;
this->y = this->y*n;
return *this;
}
It works - I've tested some print outs from main...the only issue is...I get a warning from the -Weffc++ flag! It says my function should return by value! I know this flag corresponds to the book "Effective C++" book, but I don't have a copy onhand - what does the book suggest? What is meant to pass by value?

Just to elaborate on Grizzly's comment... This is not the in-place multiplication. As such, you should declare it const to explicitly prevent that:
Coord Coord::operator*(int n) const {
Coord c(*this);
c.x *= n;
c.y *= n;
return c;
}
Or if you have a useful constructor:
Coord Coord::operator*(int n) const {
return Coord(x*n, y*n);
}
The in-place multiplication is different (and non-const):
Coord& Coord::operator*=(int n) {
x *= n;
y *= n;
return *this;
}

You haven't implemented operator* but rather you implemented the self-mutating operator*=, assigning the result back to the original object.
Consider the effects of your operator's implementation for the following int example:
int x = 5;
int y = 2;
int z = x * y;
Now, with integer multiplication implemented similarly to your code, you would end up with both y and z equal to 10.
In order to implement the normal operator* type operators you'll need to create a temporary object and return that by value.
You're probably looking for an implementation more like this (assuming you have a two parameter constructor to your class):
Coord Coord::operator*(int n) const
{
return Coord(x * n, y * n);
}
But note that often, what seems like an obvious meaning of an operator isn't so clear, and overloading simply causes confusion. Consider a non-member named function instead (using a named member scaling function), along these lines:
Coord& Coord::ScaleBy(int n)
{
this->x = this->x*n;
this->y = this->y*n;
return *this;
}
Coord ScaleCoord(Coord c, int n)
{
return c.ScaleBy(n);
}

In general, this sort of thing is done in two parts, a member operator*= and a non-member operator* that uses *=:
Coord& Coord::operator*=(int n) {
x *= n;
y *= n;
return *this;
}
Coord operator*(const Coord& c, int n) {
Coord res(c);
res *= n;
return res;
}

Related

C++ overloading of the plus operator

I want to add 2 objects, by overloading the + operator, but my compiler says there's no matching function to call to point::point(int, int). Can somebody please help me with this code, and explain the error ? thank you
#include <iostream>
using namespace std;
class point{
int x,y;
public:
point operator+ (point & first, point & second)
{
return point (first.x + second.x,first.y + second.y);
}
};
int main()
{
point lf (1,3)
point ls (4,5)
point el = lf + ls;
return 0;
}
You can just change your code like this,
#include <iostream>
using namespace std;
class point {
int x, y;
public:
point(int i, int j)
{
x = i;
y = j;
}
point operator+ (const point & first) const
{
return point(x + first.x, y + first.y);
}
};
int main()
{
point lf(1, 3);
point ls(4, 5);
point el = lf + ls;
return 0;
}
Hope this helps...
class point{
int x,y;
public:
point& operator+=(point const& rhs)& {
x+=rhs.x;
y+=rhs.y;
return *this;
}
friend point operator+(point lhs, point const& rhs){
lhs+=rhs;
return lhs;
}
};
There are a pile of little tricks above that make following this pattern a good "no brainer".
You get both += and + with the "proper" semantics.
If you chain +s together, you get elision of the left hand side operation. (ie, a+b+c becomes (a+b)+c, the return value of a+b is elided into the _+c call). If your objects have movable state, the proper moves happen for no design cost.
a+b works if either a or b is a point, and the other has an implicit-conversion-to-point. Member operator+ does not do this if a is not a point; this is pointless asymmetry.
a+=b is often more efficient to implement than a=a+b. When you implement += here, you get an efficient + as well. And your += is in turn defined in terms of member variable +=s.
The error with gdb I get is
main.cpp:8:49: error: ‘point point::operator+(point&, point&)’ must take either zero or one argument
This is because the the object that you plan to perform the operation on is this (the left hand side) and then the right hand side is the argument. If you wish to use the format that you've taken, then you can put the declaration outside the class - ie
struct point
{
// note made into a struct to ensure that the below operator can access the variables.
// alternatively one could make the function a friend if that's your preference
int x,y;
};
point operator+ (const point & first, const point & second) {
// note these {} are c++11 onwards. if you don't use c++11 then
// feel free to provide your own constructor.
return point {first.x + second.x,first.y + second.y};
}

Compound assignment operator overloading

I have seen Boost give you the possibility of doing:
v*=c where c is i.e. a double and v is a vector
How could I make, as an exercise, the overloading of *= correctly, which works in the same way of the previous example (with double on the right side)?
How about something like this?
// in class
T& operator *= (double d)
{
member *= d;
return *this;
}
// outside of class
T operator * (T v, double d)
{
v *= d;
return v;
}
Your method will look as follows:
inline vector operator *= (vector v, double &b);
It's overloaded for the class vector, should take a double, should modify the object itself and should return itself to be used as v1 = v2*= 4.2;
Since it's for an exercise, you won't post the implementation here.

Overloading operator+ in c++

I have a little problem with one of my task for exercise for exam. This is a text:
Class MyFloat have a private variable float num. You have to write methods which will enable next lines of code:
MyFloat x = 3.5;
MyFloat y = x + 3.2
float z = 3.4 + y
And I write this code:
#include <iostream>
#include <Windows.h>
using namespace std;
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
MyFloat operator+(MyFloat x)
{
float result;
result = x.num + this->num;
return result;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4 + y;
system("PAUSE");
}
I get error in this line:
float z = 3.4 + y;
It says:
error C2677: binary '+' : no global operator found which takes type 'MyFloat' (or there is no acceptable conversion)
What should I do? How to solve this problem???
Implement operator+ as non-member friend function with 2 arguments MyFloat operator+(MyFloat x, MyFloat y).
Why doesn't it work in the current version? Because member operator functions are called on the objects on the left side of the operator. In your case on the left side you have integer literal which is not an object so lacks MyFloat operator+(MyFloat x) member function.
Non-member variants of operators are symmetrical and do not require the left side being an object. Symmetricity is important because as you see in your example operator+ is not symmetrical as we are used to think in math
Edit: But this is still not enough as noted by Cassio Neri in comments. Why? See his answer for the explanation but in short: you have ambiguity problems. You can use either his solution or this one if you do manual casting like this: float z = 3.4f + static_cast<float>(y); which is quite ugly. You can use another cast: float z = MyFloat(3.4f) + y if you provide MyFloat::operator float conversion.
Another solution to solve the same ambiguity problem: In C++11 you could use your own suffix literal (similar to f prefix for built-in floats, for example 3.4_f; (underscore means that this suffix literal is user-defined). Sample implementation (given that you implement operators for casting from MyFloat to float and backwards:
MyFloat operator "" _f(long double val) {
return MyFloat(static_cast<float>(val)); }
int main() {
MyFloat x = 3.75;
MyFloat y = x + 3.2;
float z = 3.4_f + y;
}
This can be a solution:
class MyFloat
{
float num;
public:
MyFloat(float n)
{
num = n;
}
operator float() const {
return num;
}
};
int main()
{
MyFloat x = 3.75;
MyFloat y = x + 3.2f;
float z = 3.4f + y;
}
Initially, I also though about making MyFloat operator+(MyFloat, MyFloat) a non-member friend function but it still doesn't make the line
float z = 3.4 + y;
to compile. The reason is that 3.4 + y will be of type MyFloat and therefore you can't assign it to float z unless you provide a converting operator from MyFloat to float. Buth then, 3.4f + y becomes ambiguous (at least for VS 2010) because it can either call MyFloat operator+(MyFloat, MyFloat) or it can convert y to float and use the built-in operator + for floats.
You only have MyFloat + float operation, and you need to define float + MyFloat operation too. They are not the same.
Add this to your public functions:
friend float operator+ (const float& lhs, const MyFloat& rhs);
And this outside the class:
float operator+ (const float& lhs, const MyFloat& rhs) {
return lhs + rhs.num;
}
Note: Edited as per comment by CassioNeri.
While you can proceed with the answer where you define the "cast to float" approach, I believe it is better for your own sake that you start making use of your public API to implement additional behavior.
In general, a simple "casting" will not do the trick (for example, what happens if MyFloat were MyMatrix?).
The approach below is certainly more verbose, but it stresses that you should "eat your own food", meaning that you should try to implement additional behavior based on your own public interface, rather than a bunch of obscure implicit casts, or friend functions. If you use your own API: You will understand its limitations, and may potentially save recompilation of the main class if you make modifications.
Also, suppose that you wanted to count the accesses to your class (or otherwise control access to the underlying value): using the casting operator you would need to duplicate the code in operator float() and in float value().
So, here is my humble suggestion which appears longer but, to my taste, better reflects OO design principles.
#include<iostream>
class MyFloat {
public:
MyFloat(float value):
m_value(value) { }
float value() const {
return m_value;
}
private:
float m_value;
};
// Eat your own food: implement functions using your public interface
// until proven need to do otherwise. This will help you assess the
// usability of your API.
float operator+(const MyFloat& lhs, const MyFloat& rhs) { return lhs.value() + rhs.value(); }
float operator+(const MyFloat& lhs, float rhs) { return lhs.value() + rhs; }
float operator+(float lhs, const MyFloat& rhs) { return lhs + rhs.value(); }
// See, now I can define another operator without need to recompile my
// class (this could have been placed in another file)
std::ostream& operator<<(std::ostream& os, const MyFloat& mf) {
os<<"MyFloat("<<mf.value()<<")";
return os;
}
int main() {
MyFloat x = 3.5; // would not work if I had declared the constructor as "explicit"
MyFloat y = x + 3.2;
MyFloat z = 3.4 + y;
std::cout<<x<<", "<<y<<", "<<z<<std::endl;
}
Output (compiled with g++ example.cpp -Wall -Wextra):
MyFloat(3.5), MyFloat(6.7), MyFloat(10.1)

Constructing result in operator vs operating on default-constructed object

I have a class which is essentially an array with labelled contents, and I'd like to define some operators for it. I'd like to do it in such a way that changing the number of elements in the class is easy, as I expect future users will change the variables tracked, but I'd also like to ensure that basic arithmetic operations on the class are as efficient as possible.
I can see two way of implementing the operators. Taking the example of a Vector2D class:
struct Vector2D {
//members
const static int nElem = 2;
double x;
double y;
//Constructors
Vector2D() {}
Vector2D(double X, double Y) : x(X), y(Y) {}
//Operators
double& operator[] (int index) {
switch(index) {
case 0:
return x;
case 1:
return y;
default:
return std::out_of_range ("Oops");
}
}
// Option 1: operator+ by constructing result
Vector2D operator+ (const Vector2D & rhs) const {
return Vector2D(x + rhs.x, y+rhs.y);
}
// Option 2: operator+ using loop and [] operator
Vector2D operator+ (const Vector2D & rhs) const {
Vector2D result;
for(int i = 0; i < nElem; i++)
result[i] = (*this)[i] + rhs[i];
return result;
}
};
Assuming I use -03 optimization, will there be any difference between the two implementations of operator+? My understanding is that since the default Vector2D constructor has no code body and the class contents are a default data type, there is no extra overhead in Option 2 for calling the default constructor on result before setting its members. I expect the two to be equivalent, but I'm not confident enough in my knowledge to be sure.
Your method won't work at all. If you want someone to be able to change nElem you can't use x, y as your names. Why? Because changing nElem to 3 won't magically add z. And since you can't do a for loop over x and y, your definition of nElem is meaningless.
Finally, this is a textbook case for the use of a number template. Create a vector which is templated over how many elements it has.
Do something like this:
template<unsigned int LEN>
class Vector{
double v[LEN];
public:
Vector operator+(const Vector &o){
Vector res;
for (unsigned int i=0;i<LEN;++i) // with -O3 and small LEN this will be unrolled
res.v[i]=v[i]+o.v[i];
}
// ... etc.
};
Then you use it like this:
Vector<2> my_2d_vec;
Vector<3> my_3d_vec;

Returning a mutable value in C++11

I was wondering about having a method return an r-value. Specifically, I was wondering if there was a way to do this with an overloaded operator.
I have this code:
struct vec4 {
float x;
float y;
float z;
float w;
...
inline float operator [] (int i)
{
switch (i) {
case 0:
return this->x;
case 1:
return this->y;
case 2:
return this->z;
case 3:
return this->w;
default:
exit(1);
return 0;
}
}
};
How can I change this so that I could use something to the effect of
vec4 v;
...
v[2] = 5.0f;
I've hear about rvalue references in C++11, and could they be a potential solution?
EDIT: I found a way to put in my actual code.
No C++11 is needed for this. Just have:
float & operator[](std::size_t i) { return data[i]; }
Now you can say v[2] = 5; and all is well.
If you wanted, you could add a constant overload that doesn't use references and which can be used for reading the value.
float operator[](std::size_t i) const { return data[i]; }
The only time you might consider rvalue member function qualifiers is if you wanted to allow assigning to a temporary member:
vec4{}[2] = 5;
In that case, you still return a lvalue reference, but you must qualify the member function:
float & operator[](std::size_t i) && { return data[i]; }
// ^^^^
You can simply use:
float& operator [] (int index)
{
return data [i];
}
This allows you to write v[2] = 5.0f; and it will work as expected. No need for r-value references here.
You should also add a const-overload to retrieve the value, like this:
float operator [] (int index) const
{
return data [i];
}
This will allow you to write code like this: const vec4 v; float x = v[1];.
For what you want to accomplish, you apparently want to return an lvalue, not an rvalue. That's actually pretty easy:
float &operator[](size_t i) { return data[i]; }
Note that when you're defining the function inside the class definition, inline is redundant -- defining the function inside the class definition makes it inline by default.