Повторное создание экземпляра класса без использования идентификатора

Я хочу многократно создавать экземпляр класса в рамках модуля без указания уникального имени. Что-то вроде этого.

MyClass name##__LINE__(); // doesn't work because __LINE__ won't stringify
MyClass name##__LINE__(); // duplicate identifier error - two name__LINE__ variables

Есть ли способ сделать это, создав уникальное имя или используя некоторый анонимный контекст, например инициализатор или структуру?


person BSalita    schedule 25.09.2014    source источник
comment
MyClass arr[N] вариант?   -  person Anton Savin    schedule 26.09.2014


Ответы (2)


См. этот ответ

#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];

Почему эти макросы работают
Стандарт C11, 6.10.3.1 Argument substitution:

После определения аргументов для вызова функционального макроса происходит подстановка аргументов. Параметр в списке замены, если ему не предшествует маркер предварительной обработки # или ## или за ним не следует маркер предварительной обработки ## (см. ниже), заменяется соответствующим аргументом после того, как все макросы, содержащиеся в нем, были расширены. Перед заменой маркеры предварительной обработки каждого аргумента полностью заменяются макросом, как если бы они составляли остальную часть файла предварительной обработки; никакие другие токены предварительной обработки недоступны.

Соответствующий абзац в стандарте C++ (16.3.1 Argument substitution) является точной копией стандарта C.

person Anton Savin    schedule 26.09.2014
comment
Может ли кто-нибудь проверить, соответствует ли это решение стандартам? Могу ли я ожидать, что он будет работать со всеми соответствующими реализациями? - person BSalita; 26.09.2014
comment
Фантастический ответ. Спасибо! - person BSalita; 27.09.2014
comment
Обнаружено, что __LINE__ не уникален для файлов #include. Я изменил на __COUNTER__, который поддерживается Visual Studio и gcc. - person BSalita; 13.10.2014

Вам нужно дважды вложить оператор конкатенации

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__);
}
person walrii    schedule 26.09.2014