   Odd compile error under gcc but not MSVC
  Here's the (relevant) code:Vector2.hclass Vector2 {public:Vector2();Vector2(float X, float Y);Vector2(const Vector2& vector);Vector2& operator=(const Vector2& rhs);float x, y;};Vector2& operator+=(Vector2& lhs, const Vector2& rhs);Vector2 operator+(const Vector2& lhs, const Vector2& rhs);// Various other operators and functions that have different names and signatures to theseVector2.cppVector2::Vector2() : x(0.0f), y(0.0f) {}Vector2::Vector2(float X, float Y) : x(X), y(Y) {}Vector2::Vector2(const Vector2& vector) {*this = vector;}Vector2& Vector2::operator=(const Vector2 &rhs) {x = rhs.x;y = rhs.y;return *this;}Vector2& operator+=(Vector2& lhs, const Vector2 &rhs) {lhs.x += rhs.x;lhs.y += rhs.y;return lhs;}Vector2 operator+(const Vector2& lhs, const Vector2& rhs) {return Vector2(lhs) += rhs;}This works fine under MSVC, and had worked fine under gcc until today when I made operator += a non-member function rather than a member function. Now that it's not a member though, gcc gives me this rather odd-looking error:Vector2.cpp: In function 'Vector2 operator+(const Vector2&, const Vector2&)':Vector2.cpp:58: error: no match for 'operator+=' in 'Vector2(((const Vector2&)((const Vector2*)lhs))) += rhs'Vector2.cpp:29: note: candidates are: Vector2& operator+=(Vector2&, const Vector2&)What on earth does it think "Vector2(lhs) += rhs" means? I thought this was the canonical form for operator+ so it seems a bit odd that it's choking on it. It also seems odd that the candidate is listed as being from the .cpp file rather than the header when they're exactly the same declaration and the header one will have been seen first. Is it normal for gcc to refer to the latest declaration of a function like this?EDIT: note to whoever can do anything about it - the 'Show Preview' feature doesn't display the '+' symbol! Made writing this post rather odd...   
  When you made it a non-member function, you changed the operator overload from a non-const member function called on a temporary to a non-member function with the first argument being a non-const reference. In standard C++ you can't bind a temporary to a non-const reference; MSVC allows it as an extension to the language.   ;  But a named temporary will be fine? So this is standard C++:Vector2 operator+(const Vector2& lhs, const Vector2& rhs) {Vector2 temp(lhs);return temp += rhs;}?Any idea why the standard says you can't bind a temporary to a non-const reference? It seems like a perfectly safe and normal thing to do.   ;  Basically because there's a lot of different ways to generate a temporary without realizing it, which can make a function call that modifies an argument into a very expensive no-op that doesn't look like a no-op.   ;Quote:Original post by hymermanIt seems like a perfectly safe and normal thing to do.It is not a perfectly safe and normal thing to do.Consider:void f( int& i ) { i = 42; }void g() {    h = 24;    f(h);    std::cout << h << std::endl;}What does this code do?  It should print out 42, right?Right -- if h is an int.  However, what if the type of h is actually a double?It won't compile -- unless we're using the MSVC extension.  What happens then?It prints out 24.  To pass to f it has to create an unnamed temporary conversion, the changes to which will be discarded at the end of the function call.  The non const reference indicates that the function expects to be able to modify the variable, and allowing implicitly generated, very often non-obvious temporaries to be passed as non const references clearly breaks this expectation!If the programmer wills it, they can explicitly discard the temporary by explicitly naming the temporary.  Alternatively, they can document that they do not expect to be able to modify the actual value by using a const reference instead.   ;  Actually, even with extensions enabled, MSVC wouldn't compile that if h is a double.   ;  Ah, it makes perfect sense now. So thanks to you two for explaining the error, thanks to me for building my project in multiple compilers to catch exactly this sort of thing, and no thanks to gcc for its bizarre-looking error message :)   ;Quote:Original post by hymermanAh, it makes perfect sense now. So thanks to you two for explaining the error, thanks to me for building my project in multiple compilers to catch exactly this sort of thing, and no thanks to gcc for its bizarre-looking error message :)How is it bizarre?  It's very informative.Vector2.cpp: In function 'Vector2 operator+(const Vector2&, const Vector2&)':in that functionVector2.cpp:58: error: no match for 'operator+=' in 'Vector2(((const Vector2&)((const Vector2*)lhs))) += rhs'an operator+= that takes a const Vector2& on the left-hand side does not existVector2.cpp:29: note: candidates are: Vector2& operator+=(Vector2&, const Vector2&)possible candidates are an operator+= which takes a Vector2& instead;Quote:Original post by nullsquaredVector2.cpp:58: error: no match for 'operator+=' in 'Vector2(((const Vector2&)((const Vector2*)lhs))) += rhs'an operator+= that takes a const Vector2& on the left-hand side does not existIt's that bit that doesn't make sense to me. I can see that it can't find a match for operator+= but I have no idea what particular signature it's looking for. I see what looks like a cast to a pointer then to a reference, what the devil is that all about?   ;Quote:Original post by SiCraneActually, even with extensions enabled, MSVC wouldn't compile that if h is a double.Whoops, you seem to be correct.  I'm having difficulty providing an equivalent example with implicit conversions -- it seems MSVC might not be quite that dumb with it's extension.  Unfortunately, since I'm avoiding C++ these days, I can't just give an example of the last time this extension has gotten me in trouble <_<Still, the whole 'documented to be able to modify the value' bit should still apply in terms of rationale.   