Reputation: 1582
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.
Upvotes: 3
Views: 8034
Reputation: 15524
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.
Upvotes: 3
Reputation: 1804
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.
Upvotes: 2