G++ 4.7 оценивает оператор "" как родственный к макрорасширению
Я переместил некоторый код в GCC 4.7 (из 4.6) и столкнулся с несколькими ошибками компилятора и нашел проблему, описанную в руководстве по переносу GCC 4.7:
Пользовательские литералы и пробелы
Компилятор С++ в режиме ISO C11 std={c++11,c++0x,gnu++11,gnu++0x}
поддерживает определенные пользователем литералы, которые несовместимы с некоторыми действительными ISO С++ 03.
В частности, после строкового литерала теперь требуется пробел прежде чем что-то, что может быть допустимым литеральным пользователем. Возьмите действительный код ISO С++ 03
const char *p = "foobar"__TIME__;
В С++ 03 макрос TIME расширяется до некоторого строкового литерала и соединенный с другим. В С++ 11 __TIME__
не расширяется, вместо этого operator "" __TIME__
просматривается, в результате чего после диагностики:
error: unable to find string literal operator ‘operator"" __TIME__’
Это относится к любому строковому литералу, за которым следуют без пробелов некоторые макро. Чтобы исправить это, просто добавьте пробелы между строковым литералом и имя макроса.
Пока я мог исправить ошибки, я хотел бы знать, почему я должен это делать. __TIME__
- это макрос, поэтому "something"__TIME__
изменится на "something""15:52:03"
(или аналогичный) на этапе предварительной обработки, поэтому у компилятора никогда не будет возможности увидеть его как operator ""
.
Является ли это стандартизированным поведением или это ошибка?
Ответы
Ответ 1
Проблема заключается в том, что "foobar"__TIME__
больше не токенируется в токенах препроцессора "foobar"
, а затем __TIME__
.
Знаки препроцессора "имеют лексическую форму ключевого слова, идентификатора, литерала, оператора или пунктуатора." Добавление пользовательских литералов изменяет то, что лексируется как токен препроцессора. Теперь "foobar"__TIME__
представляет собой однозначный токен препроцессора, определяемый пользователем, и поэтому, когда происходит фаза 4 перевода, которая заменила бы __TIME__
на "15:52:03"
, токер __TIME__
не будет заменен таким образом.
Да, это поведение указано в стандарте.
Из-за макросов cinttypes это похоже на то, что на него влияет больше кода, чем комитет понял, и они рассматривают его. Некоторые компиляторы уже перемещаются, чтобы справляться с проблемами с cinttypes, но не таким образом, чтобы это исправить это использование __TIME__
для вас. Я считаю, что лучше всего изменить код.