Зачем нужен двойной уровень непрямолинейности для макросов?

На: C++ FAQ - Разные технические вопросы - [39.6] Что нужно делать с макросами, которым нужно вставить две лексемы вместе?

Может кто-нибудь объяснить мне почему? Все, что я читаю, это trust me, но я просто не могу просто довериться чему-то, потому что кто-то так сказал.

Я попробовал этот подход и не могу найти никаких ошибок:

#define mymacro(a) int a ## __LINE__
mymacro(prefix) = 5;
mymacro(__LINE__) = 5;
int test = prefix__LINE__*__LINE____LINE__; // fine

Так почему я должен сделать это вот так (цитата с веб-страницы):

Однако вам нужен двойной уровень косвенности, когда вы используете ##. В основном вам нужно создать специальный макрос для "вставки маркеров", такой как как:

 #define NAME2(a,b) NAME2_HIDDEN(a,b)
 #define NAME2_HIDDEN(a,b) a ## b 

Поверьте мне - вам действительно необходимо сделать это! (И пожалуйста, никто не пишите мне, что иногда это работает без второго уровня косвенности. Попробуйте конкатенировать символ с __ LINE__ и посмотрите, что получится.)

Edit: Может кто-нибудь также объяснить, почему он использует NAME2_HIDDEN до того, как он объявлен ниже? Кажется более логичным определить макрос NAME2_HIDDEN до того, как я его использую. Может быть, здесь есть какая-то хитрость?

24
задан TWOF 24 May 2016 в 05:26
поделиться

1 ответ

У Криса Додда есть отличное объяснение первой части вашего вопроса. Что касается второй части, касающейся последовательности определений, короткая версия состоит в том, что директивы #define сами по себе вообще не оцениваются; они оцениваются и раскрываются только тогда, когда символ находится в другом месте файла. Например:

#define A a  //adds A->a to the symbol table
#define B b  //adds B->b to the symbol table

int A;

#undef A     //removes A->a from the symbol table
#define A B  //adds A->B to the symbol table

int A;

Первый int A; становится int a;, потому что именно так A определяется в этой точке файла. Второе int A; становится int b; после двух разложений. Сначала он расширяется до int B;, потому что A определяется как B в этой точке файла. Затем препроцессор распознает, что B является макросом, когда он проверяет таблицу символов. B затем расширяется до b.

Единственное, что имеет значение, это определение символа в точке расширения, независимо от того, где находится определение.

3
ответ дан 28 November 2019 в 23:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: