Анонимные переменные C++

Почему это не сработает?

 0. #define CONCAT(x, y) x ## y
 1. 
 2. #define VAR_LINE(x) \
 3.     int CONCAT(_anonymous, __LINE__) = x
 4. 
 5. #define VAR_LINE2(x) \
 6.     int _anonymous ## x = 1
 7.
 8. int main()
 9. {
10.     VAR_LINE(1);
11.     VAR_LINE(1);
12.     VAR_LINE(1);
13.     VAR_LINE2(__LINE__);
14. }

Результат вышеупомянутого расширения макроса

int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous13 = 1;

Было бы удобно, если бы мне не пришлось писать этот макрос __LINE__ в качестве аргумента.

Думаю, проблема ясна. Я хочу иметь возможность генерировать анонимные переменные, чтобы этот макрос не выходил из строя с ошибкой переопределения при объявлении нескольких переменных в одной области. Моя идея состояла в том, чтобы использовать предопределенный макрос __LINE__, потому что никакая переменная никогда не будет объявлена ​​в той же строке, как эта. Но меня беспокоит расширение макросов, не могли бы вы помочь?

Обновление: правильный ответ

Спасибо Люку Турэлю. Однако с предложенным решением возникла небольшая проблема. Между операндами и оператором ## должен быть пробел (очевидно, в стандарте сказано иное, но GCC со вкусом PS3 не расширил бы макрос должным образом, если бы между оператором и операндами не было пробелов).

#define _CONCAT(x,y) x ## y
#define CONCAT(x,y) _CONCAT(x,y)

Макрос VAR_LINE теперь дает:

int _anonymous10 = 1;
int _anonymous11 = 1;
int _anonymous12 = 1;

Было подтверждено, что это работает под Win32 (Visual Studio 2008), XBOX360 (Xenon) и PS3.

Нет, я понимаю, почему вы так думаете. Анонимные переменные имеют множество применений. Мне нужно, чтобы продолжительность объектов была в области видимости. Без имени, анонимно оно или нет, они просто будут созданы и сразу после этого уничтожат тот же самый объект.

John Leidegren 20.01.2009 19:43

Но это означает, что вы полагаетесь на побочные эффекты. Если для метода требуется наличие определенного объекта, передайте этот объект в качестве параметра. Сделайте зависимость явной, это упростит обслуживание. Я предполагаю, что вы должны использовать интерфейс в стиле singleton для доступа к анонимным объектам?

Skizz 21.01.2009 12:59

В целом «анонимность - это плохо» - кто-то в будущем забудет создать объект и не осознает его важность до тех пор, пока программа не выйдет из строя, и даже тогда он не будет полностью уверен, почему. Называя объект и передавая его в качестве параметра, вы обнаружите ошибку во время компиляции.

Skizz 21.01.2009 13:03

У вас также есть проблемы с потоками - что, если два потока создают один и тот же анонимный объект - какой из них следует использовать?

Skizz 21.01.2009 13:05

Нет проблем с потоками, и анонимные объекты недоступны. Их единственная цель здесь - обеспечить время жизни объекта, и для этого требуется имя. Будь то анонимно или нет. Пример никоим образом не передает то, что я пытаюсь сделать, и поэтому я понимаю, что это может сбивать с толку.

John Leidegren 07.02.2009 14:36

Это не принципиально неправильно. В C++ 11 следовало добавить ключевое слово для анонимных переменных, чтобы не использовать макросы. Возможно, что-то вроде: int auto; Позволяет использовать ключевое слово auto вместо имени переменной. Да, это позволяет такие вещи, как «auto auto = 5.f;»

cmeub 27.11.2012 23:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
6
2 922
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужно добавить уровень косвенности, чтобы __LINE__ был расширен:

#define _CONCAT_(x,y) x ## y
#define CONCAT(x,y) _CONCAT_(x,y)

#define VAR_LINE(x) int CONCAT(_anonymous, __LINE__) = x

Вот в чем дело, есть проблема с предложенным вами решением. Между операндами и оператором ## должен быть пробел. Предлагаемое вами решение должно быть следующим: #define _CONCAT_ (x, y) x ## y.

John Leidegren 21.01.2009 18:40

Что ж, это странно, в стандарте специально указано, что «Пробел вокруг токенов # и ## в определении макроса необязателен». (16.3.5 п.6). В любом случае, я соответствующим образом отредактирую свой ответ.

Luc Touraille 21.01.2009 19:15

Действительно, я проверил это и с людьми на работе. Судя по всему, GCC со вкусом PS3 не расширил бы макрос должным образом, если бы между оператором и операндами не было пробелов.

John Leidegren 22.01.2009 13:44

Другие вопросы по теме