Заменены ли триграфные замены при создании необработанной строки путем конкатенации? - PullRequest
9 голосов
/ 28 июля 2011

Довольно часто встречаются макросы и токены для переключения между широкими и узкими строками во время компиляции.

#define _T(x) L##x
const wchar_t *wide1 = _T("hello");
const wchar_t *wide2 = L"hello";

И в C ++ 11 должно быть допустимо придумать подобную вещь с необработанными строками:

#define RAW(x) R##x
const char *raw1 = RAW("(Hello)");
const char *raw2 = R"(Hello)";

Поскольку расширение макроса и объединение токенов происходит до замены escape-последовательности, это должно предотвратить замену escape-последовательностей в строке в кавычках.

Но как это относится к триграфам? Необработанные строки, сформированные путем конкатенации с обычными строками, все еще подлежат обращению к их заменам триграфа?

const char *trigraph = RAW("(??=)");      // Is this "#" or "??="?

Ответы [ 2 ]

6 голосов
/ 11 марта 2012

Нет, в вашем примере триграф не возвращается.

[lex.phases]p1 определяет три фазы перевода, относящиеся к вашему вопросу:

1. Последовательности триграфа заменяются соответствующими односимвольными внутренними представлениями.
3. Исходный файл разлагается на токены предварительной обработки.
4. Макро вызовы расширены.

Фаза 1 определяется [lex.trigraph]p1. На этом этапе ваш код переводится на const char *trigraph = RAW("(#)").

Фаза 3 определяется [lex.pptoken]. На этой стадии триграфы возвращаются в виде необработанных строковых литералов. Пункт 3 гласит:

Если следующий символ начинает последовательность символов, которые могут быть префиксом и начальной двойной кавычкой необработанного строкового литерала, такого как R ", следующий токен предварительной обработки должен быть необработанным строковым литералом. Между начальной и окончательной двойной кавычкой символы необработанной строки, любые преобразования, выполняемые на этапах 1 и 2 (триграфы, имена универсальных символов и объединение строк), возвращаются.

Это не так в вашем примере, поэтому триграф не возвращается. Ваш код преобразуется в токен предварительной обработки последовательность const char * trigraph = RAW ( "(#)" )

Наконец, на этапе 4 макрос RAW раскрывается, и происходит вставка токена, в результате чего получается следующая последовательность preprocessing-tokens : const char * trigraph = R"(#)". r-char-sequence строкового литерала содержит #. Этап 3 уже наступил, и нет другой точки, в которой происходит возврат триграфов.

0 голосов
/ 28 июля 2011

Подстановка триграфа происходит перед обработкой макроса.

UPD Пожалуйста, не обращайте на это внимания. Я не понял, что c ++ 0x возвращает триграфы в необработанных строковых литералах.

UPD2 2.5.3 описывает процесс формирования необработанных-буквально-литеральных токенов предварительной обработки. Обращение триграфа является частью этого процесса. Не существует необработанных строковых литералов, которые не являются токенами предварительной обработки. Таким образом, ответ на ваш вопрос, кажется, да.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...