# Odd compile error under gcc but not MSVC

This topic is 3500 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Here's the (relevant) code: Vector2.h
class 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 these


Vector2.cpp
Vector2::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...

##### Share on other sites
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.

##### Share on other sites
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.

##### Share on other sites
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.

##### Share on other sites
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.

##### Share on other sites
Actually, even with extensions enabled, MSVC wouldn't compile that if h is a double.

##### Share on other sites
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 :)

##### Share on other sites
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 function

Vector2.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 exist

Vector2.cpp:29: note: candidates are: Vector2& operator+=(Vector2&, const Vector2&)
possible candidates are an operator+= which takes a Vector2& instead

##### Share on other sites
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 exist

It'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?

##### Share on other sites
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.

1. 1
2. 2
Rutin
19
3. 3
4. 4
khawk
15
5. 5

• 13
• 26
• 10
• 11
• 44
• ### Forum Statistics

• Total Topics
633743
• Total Posts
3013644
×