I'm trying to build for android some C++ code, that already working on win32. I have a problem, with overloaded operators. For example:
Code:
Vector2 uv0 = textures.back()->m_uv0;
Vector2 uvt = textures.back()->m_uvt;
uv0 = m_uv0 + Vector2(uv0.x * m_uvt.x, uv0.y * m_uvt.y) + Vector2(0.01f,0.01f);
Where Vector2 is a class declarated above. The declaration of it is:
class Vector2
{
public:
//Constructors
Vector2() : x(0.0f), y(0.0f){}
Vector2(GLfloat _x, GLfloat _y) : x(_x), y(_y) {}
Vector2(double _x, double _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(int _x, double _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(double _x, int _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(int _x, int _y) : x(static_cast<float>(_x)), y(static_cast<float>(_y)) {}
Vector2(GLfloat * pArg) : x(pArg[0]), y(pArg[1]) {}
Vector2(const Vector2 & vector) : x(vector.x), y(vector.y) {}
//Vector's operations
GLfloat Length();
Vector2 & Normalize();
Vector2 operator + (Vector2 & vector);
Vector2 & operator += (Vector2 & vector);
Vector2 operator - ();
Vector2 operator - (Vector2 & vector);
Vector2 & operator -= (Vector2 & vector);
Vector2 operator * (GLfloat k);
Vector2 & operator *= (GLfloat k);
Vector2 operator / (GLfloat k);
Vector2 & operator /= (GLfloat k);
Vector2 & operator = (Vector2 vector);
Vector2 Modulate(Vector2 & vector);
GLfloat Dot(Vector2 & vector);
void Set(GLfloat _x, GLfloat _y);
//access to elements
GLfloat operator [] (unsigned int idx);
//data members
float x;
float y;
};
The definition of this class I won't list here, because it doesn't metter.
But unfortunately I recive an error:
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/Sprite.cpp: In member function'void Sprite::AddTex(TEX::GUItex)':
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/Sprite.cpp:103:57: error: no match for 'operator+' in '((Sprite*)this)->Sprite::m_uv0 + Vector2((uv0.Vector2::x *((Sprite*)this)->Sprite::m_uvt.Vector2::x), (uv0.Vector2::y * ((Sprite*)this)->Sprite::m_uvt.Vector2::y))'
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/Sprite.cpp:103:57: note: candidates are:
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/SBMath.h:38:10: note: Vector2 Vector2::operator+(Vector2&)
G:/PROJECT266/projects/PROJECT266//jni/../jni/SBE/source/SBMath.h:38:10: note: no known conversion for argument 1 from 'Vector2' to 'Vector2&'
But, if I rewrite the code above like this:
Vector2 uv0 = textures.back()->m_uv0;
Vector2 uvt = textures.back()->m_uvt;
Vector2 vec1 = Vector2(uv0.x * m_uvt.x, uv0.y * m_uvt.y);
Vector2 vec2 = Vector2(0.01f,0.01f);
uv0 = m_uv0 + vec1 + vec2;
There wouldn't be any errors during compilation.
I can't understand, what is the cause of this silly error.
I would be very pleased, if you explain me how to solve this problem.
It is not possible to bind an r-value to a non-const reference.
This line:
uv0 = m_uv0 + Vector2(uv0.x * m_uvt.x, uv0.y * m_uvt.y) + Vector2(0.01f,0.01f);
is equivalent to: (I replaced the parameters with PARAMS to make my example more readable):
uv0 = (m_uv0.operator+(Vector2(PARAMS))).operator+(Vector2(PARAMS));
Here Vector2(PARAMS) will create a temporary object. That is you are trying to pass an r-value reference to your operator overload and the compiler will not find a match as your operator is declared as:
Vector2 operator+ (Vector2& vector);
For more info about why temporaries can't be bound to non-const references see this: How come a non-const reference cannot bind to a temporary object?
In the second example you first declare two Vector2 objects and then pass them to the operator as l-value references which matches your operator overload.
One way to solve the issue and let the operator overload take both l-value and r-value references is to declare it as taking a reference to const as it is perfectly fine to bind an r-value to a reference to const. See the answer by krsteeve for how this can be done.
In general you should always declare functions taking references as taking reference to const if you don't intend to modify the argument.
Examples of reference binding:
Vector2& ref1 = Vector2(); // Error, trying to bind r-value to non-const ref.
Vector2 v;
Vector2& ref2 = v; // OK, v is an l-value reference.
// It is however OK to bind an r-value to a const reference:
const Vector& ref3 = Vector2(); // OK.
You're trying to pass in temporary objects as non-const references. Change the signature of your operator + to take a const references:
Vector2 operator + (const Vector2 & vector);
The reason your second sample works is that you're now naming the Vector2 objects, they're no longer temporary.
Related
I am writing a class for a 2D Vector and need to do a dot product.
I have overloaded the * operator to do this, but when it comes time to perform this * this it gives me an error:
class Vector2 {
private:
float x, y;
public:
Vector2(float _x, float _y) {
x = _x;
y = _y;
}
// Dot product
float operator*(const Vector2& other) {
return x * other.x + y * other.y;
}
// Magnitude (abs)
float Magnitude() {
float dot = (this) * (this); // HERE IS THE ERROR: expression must have arithmetic or unscoped enum type
return std::sqrt(dot);
}
Vector2 operator+(const Vector2& other) {
return Vector2(x + other.x, y + other.y);
}
};
The error is: expression must have arithmetic or unscoped enum type
Any help is appreciated! Thank You :)
The this keyword is a pointer, not an actual object.
The correct code is therefore (*this) * (*this).
I am getting error in the operator overloading definition. The error goes away if I remove the consts in the parameters. Is there any way I can get it working without removing the consts in the parameters? Also what is happening behind them?
class Vector3D{
public:
float x, y, z;
float dot(Vector3D& v) {
return x * v.x + y * v.y + z * v.z;
}
};
inline float operator *(const Vector3D& a, const Vector3D& b) {
return a.dot(b);
}
You should qualify the member function dot as const as well, otherwise you can't call this member function on a const object:
float dot(Vector3D const& v) const { // <-- const here
You also need to accept v by const& since you are passing it a const object.
You didn't include the error, but it says something like : "cannot call non-const method on const object". Your dot does not modify members and should be declared as const also the argument is not modifed, hence should be const:
class Vector3D{
public:
float x, y, z;
// v---------------- allow to call on const objects
float dot(const Vector3D& v) const {
// ^---------------------------------- pass parameters as const ref
return x * v.x + y * v.y + z * v.z;
}
};
inline float operator *(const Vector3D& a, const Vector3D& b) {
return a.dot(b);
}
In the Vector3D::dot function, neither the object for member function call nor the argument object are modified.
To tell this to the compiler, you should add two consts to your dot definition.
class Vector3D{
public:
float x, y, z;
float dot(const /*(1)*/ Vector3D& v) const /*(2)*/ {
return x * v.x + y * v.y + z * v.z;
}
};
inline float operator *(const Vector3D& a, const Vector3D& b) {
return a.dot(b);
}
(1) : telling that the argument object is not modified
(2) : telling that the object for member function call is not modified
now i am stumbling with c++ code problem.
i made a simple structure 'Vector3' in that i defined the operator+.
and when i use that operator inside const function, it show a red line.
struct Vector3 {
float x, y, z;
Vector3 operator+ (const Vector3 v) {
return Vector3(x + v.x, y + v.y, z + v.z);
};
Vector3(float x, float y, float z) : x(x), y(y), z(z) {};
};
// and i use it inside some const function
struct SomeST {
Vector3 a,b;
Vector3 Function() const
{
return a + b; // error
}
};
and if i delete the const from function, it works!
so it would be amazing if someone can explain what's going on under the hood.
thanks.
Function
Vector3 Function() const
is const. Which means, that this is const inside the function. Which in turn means both a and b are const. a + b syntax is fancy way for writing a.operator + (b) (call operator + method on object a with argument b). Now a is const, so a.operator + method must also be const. Since you've not supplied such operator (the operator you've written is not const) your compiler highlights this as error and if you try to compile it, you will get const based error.
You need to suply operator + (...) const, which in this exact case means you need to add const keyword to definition:
Vector3 operator+ (const Vector3 v) const { ... }
#include <iostream>
using namespace std;
class Point {
private:
int x, y; // Private data members
public:
Point(int x = 0, int y = 0); // Constructor
int getX() const; // Getters
int getY() const;
void setX(int x); // Setters
void setY(int y);
void print() const;
const Point operator+(const Point & rhs);
// Overload '+' operator as member function of the class
};
int main(int argc, char** argv)
{
Point p1(1, 2), p2(4, 5);
// Use overloaded operator +
Point p3 = p1 + p2;
p1.print(); // (1,2)
p2.print(); // (4,5)
p3.print(); // (5,7)
// Invoke via usual dot syntax, same as p1+p2
Point p4 = p1.operator+(p2);
p4.print(); // (5,7)
// Chaining
Point p5 = p1 + p2 + p3 + p4;
p5.print(); // (15,21)
return 0;
}
// Constructor - The default values are specified in the declaration
Point::Point(int x, int y) : x(x), y(y) { } // Using initializer list
// Getters
int Point::getX() const { return x; }
int Point::getY() const { return y; }
// Setters
void Point::setX(int x) { this->x
= x; } // (*this).x = x; x = x
void Point::setY(int y) { this->y = y; }
// Public Functions
void Point::print() const {
cout << "(" << x << "," << y << ")" << endl;
}
// Member function overloading '+' operator
const Point Point::operator+(const Point & rhs) {
return Point(x + rhs.x, y + rhs.y);
}
I'm studying operator overloading and I don't understand why I get the error.
error: no match for 'operator+' (operand types are 'const Point' and 'Point')
I deleted const qualifier at the end of the operator+ function on purpose in order to understand it. Can someone explain explicitly why I need it?
The member
const Point Point::operator+(const Point & rhs);
is a non-const member, i.e. requires the lhs of the operation to be mutable, but (as the error message shows) you require an operation with a const lhs. Hence, you must declare the operator as such
Point Point::operator+(const Point & rhs) const;
Note that I also removed the const for the return type, as it is deprecated.
Why do you need the const? The natural + operator (for example between arithmetic types) does not alter its arguments and, as a consequence, the usual (human) conventions for using this operator implicitly assume that the arguments are not altered. In your particular case, the return of a+b was explicitly const (though that is deprecated AFAIK), so that in a+b+c = (a+b)+c the lhs is const and your non-const member function cannot be used.
Moreover, whenever a member function does not alter the state of its object, it should be declared const, so that it can be called for const object.
Alternatively, this operator can be defined as non-member function friend
Point operator+(const Point&lhs, const Point&rhs);
which more clearly expresses the symmetry between lhs and rhs (the corresponding function for your non-const member would have been
Point operator+(Point&lhs, const Point&rhs);
).
You need to define your method as a constone, i.e.:
const Point operator+(const Point & rhs) const;
p1+p2 returns a const Point so you need a const Point + const Point operator to be able to compute (p1+p2)+p3.
Good answers, but they don't explain why the const is an issue. The simple reason is chaining order and operator type matching.
Point p5 = p1 + p2 + p3 + p4;
// is interpreted as:
Point p5 = ConstPoint( (Point(p1)).operator+((const Point&)(p2)) + p3 + p4;
// as operator+ is left-to-right , not right-to-left !!!
Point and const Point are different types, so in the first iterpretation, you have a:
p5 = const Point(sumP1P2) . operator+ (Point(P3)) /*+ P4 awaiting interpretation */;
// whose search will be for a const LHS - i.e. "Point operator=(constPointRef) const;" - which is bound to fail.
The following will work:
const P& operator+(const P& rhs) const; // corresponds to const P& result = const P& lhs + const P& rhs
P operator+(P rhs) const; // corresponds to copy-by-value for all operands.
The only problem is "const" Point operator+(const Point & rhs); remove that in the def and dec .. it will work
This question already has answers here:
overloading operator * c++
(2 answers)
Closed 9 years ago.
I am trying to make a vector class in c++. I have overloaded the * operator like this:
class vector2
{
public:
vector2(float x, float y);
static vector2 vector_zero;
float x, y;
float length() const;
string to_string();
vector2 operator+(vector2 other);
vector2 operator*(float other);
};
vector2 vector2::operator*(float other)
{
return vector2(x * other, y * other);
}
It works fine when I write "vector2(3,4) * 2" but I want it to work when I write "2 * vector(3,4)" too.
How can I do that?
You need to create another operator* (outside of the class) like this:
vector2 operator*(float other, vector2 v){
return v*other;
}
Side note:
you forgot a lot of the const declarations, an I also recommend using reference (&) for classes. I would also make these functions inline, because they are so small:
class vector2
{
public:
...
string to_string() const;
inline vector2 operator+(const vector2 &other)const;
inline vector2 operator*(float other)const;
};
inline vector2 operator*(float other, const vector2 &v){
return v*other;
}