12

I was coding and accidentally left out a space between a constant reference and its default value. I was surprised to see that it came up as an error in Intellisense, so I compiled it, and sure enough, it doesn't work in GCC 4.3.4, 4.5.1, or 4.7.2, and doesn't work in Visual Studio 2012, either.

Here's an equivalent sample that demonstrates the error:

struct S {
    S(const int &= 5){}    
};

int main(){}

This yields the following error in GCC, and similar ones in MSVC:

error: expected ',' or '...' before '&=' token

I presume this is because &= is being treated as an operator, but I don't know exactly what to search for in the standard to find more information about this case. &= just comes up with operator-specfic information.

Being curious, I decided to swap it out for an rvalue reference:

S(int &&= 5){}

Strangely enough, this compiles fine on both GCC 4.7.2 and MSVC, which means that &= isn't always lexically paired as an operator.

Why does it work with an rvalue reference, but not an lvalue reference, and what does the standard have to say on the matter?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
chris
  • 60,560
  • 13
  • 143
  • 205

2 Answers2

14

This is generally known as the "principle of longest match", or the "maximal munch". Because && is a valid token and &&= is not (there's no compound-assignment notation for &&), the longest token that &&= starts with is &&; after that's been removed, there's no opportunity for &= to be seen as a single token.

This principle is common to many languages, though there are often exceptions to it. For example, in C++11, >> will be analyzed as > followed by > in a context like std::vector<std::vector<int>>.

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • Does this mean we might see an addendum for `&=` just like we did with `>>` when used with templates? – chris Nov 29 '12 at 21:05
  • @chris unlikely since `>>` was just ugly and annoying, and `&=` in argument lists would be `& =` (spaces around `=`) in any respectable code style. –  Nov 29 '12 at 21:06
  • 1
    @chris: unlikely, since we still have [problems with `>>>`](http://stackoverflow.com/questions/6235907/how-is-lexed-in-c0x). – Yakov Galka Nov 29 '12 at 21:07
  • @chris: I wouldn't expect that, but I really don't know. From what I understand, a major factor motivating the change with `>>` was that compilers were recognizing it *anyway* for the sake of giving useful error-messages: so it was already being implemented as a special case, just a special case that didn't work. That doesn't seem to be happening with `&=`. – ruakh Nov 29 '12 at 21:09
  • @ruakh, Good point with the compilers treating it specially. It's not much extra work for them to change it if they've already implemented it as well. I guess that situation ultimately occurred much more often than this one would, though. – chris Nov 29 '12 at 21:13
  • 1
    Unused/unnamed rvalue-ref parameter with default value of 5? – jrok Nov 29 '12 at 21:19
  • @jrok, Eh, technically, this was in my declaration, so it was named in the definition. I just condensed it to what would be a linkable program without the extra code :p – chris Nov 29 '12 at 21:23
6

The parser just works left to right, regardless of associativity, so in the first example, the first full token it finds is the &=. (At that moment, the parser doesn't check for larger constructs yet, so all it knows is that there's that token there.)

In the second example, the token it finds is &&. Because &&= is not a token!

Mr Lister
  • 45,515
  • 15
  • 108
  • 150