Я хочу повторно создать экземпляр класса в области видимости модуля, не предоставляя уникального имени. Что-то вроде этого.
MyClass name##__LINE__(); // doesn't work because __LINE__ won't stringify
MyClass name##__LINE__(); // duplicate identifier error - two name__LINE__ variables
Есть ли способ сделать это, либо создать уникальное имя, либо использовать анонимный контекст, такой как инициализатор или структура?
Увидеть этот ответ
#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __LINE__)
MyClass MAKE_UNIQUE(name);
MyClass MAKE_UNIQUE(name);
...
Или просто сделать массив:
MyClass arr[N];
Почему эти макросы работают
Стандарт С11, 6.10.3.1 Argument substitution
:
После того, как аргументы для вызова функционально-подобного макроса были определены,
замена аргумента имеет место. Параметр в списке замены, если не предшествует
по#
или же##
токен предварительной обработки или сопровождается##
токен предварительной обработки (см. ниже)
заменяется соответствующим аргументом после того, как все содержащиеся в нем макросы были
расширен. Перед заменой токены предварительной обработки каждого аргумента
полностью замененные макросы, как будто они образуют остальную часть файла предварительной обработки; нет другого
токены предварительной обработки доступны.
Соответствующий абзац в стандарте C ++ (16.3.1 Argument substitution
) является точной копией стандарта Си.
Вам нужно двойное гнездо оператора конкатенации
struct A{};
#define JOIN(X, Y) JOIN_DETAIL(X, Y)
#define JOIN_DETAIL(X, Y) JOIN_DETAIL2(X, Y)
#define JOIN_DETAIL2(X, Y) X##Y
int main() {
A JOIN(a, __LINE__);
A JOIN(a, __LINE__);
}