В настоящее время я работаю в VS2022 и пишу набор макросов, используя приемы с вариационными макросами, описанные в разделе «Перегрузка макроса по количеству аргументов». В частности, я пытаюсь сделать три вещи с типами с ограниченной областью: одна — сгенерировать сам тип с ограниченной областью, одна — создать строковый литерал типа с ограниченной областью, а третья — попытаться создать имя переменной из типа с ограниченной областью, заменив :: с _. Пока что мои макросы выглядят так:
Для справки: у меня включен /Zc:preprocessor, чтобы сделать препроцессор совместимым. Может ли кто-нибудь объяснить, почему только один случай терпит неудачу, когда другие успешны? Я также пробовал заменить _ другими символами на случай, если это будет проблемой, но никаких изменений не произошло.
В настоящее время я работаю в VS2022 и пишу набор макросов, используя приемы с вариационными макросами, описанные в разделе «Перегрузка макроса по количеству аргументов». В частности, я пытаюсь сделать три вещи с типами с ограниченной областью: одна — сгенерировать сам тип с ограниченной областью, одна — создать строковый литерал типа с ограниченной областью, а третья — попытаться создать имя переменной из типа с ограниченной областью, заменив :: с _. Пока что мои макросы выглядят так: [code]#define GET_ARGS(_1, _2, _3, _4, _5, ARGS, ...) ARGS
// these generate the actual scoped name #define SCOPE1(_1) _1 #define SCOPE2(_1, ...) _1##::## SCOPE1(__VA_ARGS__) #define SCOPE3(_1, ...) _1##::## SCOPE2(__VA_ARGS__) #define SCOPE4(_1, ...) _1##::## SCOPE3(__VA_ARGS__) #define SCOPE5(_1, ...) _1##::## SCOPE4(__VA_ARGS__) #define GET_SCOPE(...) GET_ARGS(__VA_ARGS__, SCOPE5, SCOPE4, SCOPE3, SCOPE2, SCOPE1)(__VA_ARGS__)
// these generate a string of the scoped name #define STR1(_1) #_1 #define STR2(_1, ...) #_1 "::" STR1(__VA_ARGS__) #define STR3(_1, ...) #_1 "::" STR2(__VA_ARGS__) #define STR4(_1, ...) #_1 "::" STR3(__VA_ARGS__) #define STR5(_1, ...) #_1 "::" STR4(__VA_ARGS__) #define GET_STR(...) GET_ARGS(__VA_ARGS__, STR5, STR4, STR3, STR2, STR1)(__VA_ARGS__)
// these generate a name for a variable #define VAR1(_1) _1 #define VAR2(_1, ...) _1##_## VAR1(__VA_ARGS__) #define VAR3(_1, ...) _1##_## VAR2(__VA_ARGS__) #define VAR4(_1, ...) _1##_## VAR3(__VA_ARGS__) #define VAR5(_1, ...) _1##_## VAR4(__VA_ARGS__) #define GET_VAR(...) GET_ARGS(__VA_ARGS__, VAR5, VAR4, VAR3, VAR2, VAR1)(__VA_ARGS__) [/code] Чтобы проверить это, у меня есть простой тестовый код: [code]namespace ns1 { namespace ns2 { struct cls {}; } }
GET_SCOPE(int) i; GET_SCOPE(ns1, ns2, cls) v;
const char* sv = GET_STR(ns1, ns2, cls);
int GET_VAR(ns1, ns2, cls); [/code] Первые три случая работают отлично и дают именно те результаты, которые мне нужны: [code]int i; ns1::ns2::cls v;
const char* sv = "ns1" "::" "ns2" "::" "cls"; [/code] Однако последний случай не удался по непонятным мне причинам. IDE разрешает это как [code]int ns1_VAR2(ns2, cls);[/code] Для справки: у меня включен /Zc:preprocessor, чтобы сделать препроцессор совместимым. Может ли кто-нибудь объяснить, почему только один случай терпит неудачу, когда другие успешны? Я также пробовал заменить _ другими символами на случай, если это будет проблемой, но никаких изменений не произошло.