Я кодировал и случайно пропустил пробел между константной ссылкой и ее значением по умолчанию. Я был удивлен, увидев, что в Intellisense это было ошибкой, поэтому я скомпилировал его и, конечно же, он не работает в GCC 4.3.4, 4.5.1 или 4.7.2 и не работает в Visual Studio 2012, либо.
Вот эквивалентный пример, который демонстрирует ошибку:
struct S {
S(const int &= 5){}
};
int main(){}
Это приводит к следующей ошибке в GCC и аналогичных в MSVC:
ошибка: ожидается «,» или «…» раньше «&= ‘токен
Я полагаю, это потому, что &=
рассматривается как оператор, но я не знаю точно, что искать в стандарте, чтобы найти больше информации об этом случае. &= просто приходит с конкретной для оператора информацией.
Будучи любопытным, я решил поменять его на референсную ссылку:
S(int &&= 5){}
Как ни странно, это прекрасно компилируется как на GCC 4.7.2, так и на MSVC, что означает, что &= не всегда лексически спарен как оператор.
Почему он работает со ссылкой rvalue, а не ссылкой lvalue, и что стандарт должен сказать по этому вопросу?
Это обычно известно как «принцип самого длинного совпадения», или «максимальный хруст». Так как &&
является действительным токеном и &&=
нет (нет записи составного присваивания для &&
), самый длинный токен, который &&=
начинается с &&
; после того, как это было удалено, нет никакой возможности для &=
быть замеченным как один жетон.
Этот принцип является общим для многих языков, хотя из него часто бывают исключения. Например, в C ++ 11, >>
будет проанализирован как >
с последующим >
в контексте, как std::vector<std::vector<int>>
,
Парсер работает слева направо, независимо от ассоциативности, поэтому в первом примере первый полный токен, который он находит, это &=
, (В этот момент синтаксический анализатор еще не проверяет наличие более крупных конструкций, поэтому он знает только то, что там есть этот токен.)
Во втором примере токен, который он находит, &&
, Так как &&=
это не знак!