了解为什么某些预处理器宏重载不起作用

问题描述 投票:0回答:1

我目前正在 VS2022 中使用参数数量上的重载宏中描述的可变参数宏技巧编写一组宏。具体来说,我尝试使用作用域类型做三件事:一是生成作用域类型本身,一是创建作用域类型的字符串文字,一是尝试通过替换来从作用域类型创建变量名

::
_
。到目前为止我的宏看起来像这样:

#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__)

为了测试这一点,我有这个简单的测试代码:

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);

前三个案例效果很好,并且产生了我想要的结果:

int i;
ns1::ns2::cls v;

const char* sv = "ns1" "::" "ns2" "::" "cls";

但是,最后一个案例因我不明白的原因而失败。 IDE 将其解析为

int ns1_VAR2(ns2, cls);
作为记录,我确实启用了
/Zc:preprocessor
以使预处理器兼容。谁能解释为什么只有一个案例失败而其他案例都成功了?我还尝试将
_
替换为其他字符,以防万一出现问题,但没有任何变化。

c++ macros visual-studio-2022 preprocessor-directive
1个回答
0
投票

问题是

##
标记粘贴发生在正文中的其他宏被扫描以进行扩展之前。 如果您希望首先扩展这些宏,则需要将它们放入不直接使用 ##
 的其他宏的参数中(因为 
##
 也会抑制参数预扫描)。  所以你需要:

// these generate a name for a variable #define CONCAT_US(_1, _2) _1##_##_2 #define EXPAND_CONCAT_US(_1, _2) CONCAT_US(_1, _2) #define VAR1(_1) _1 #define VAR2(_1, ...) EXPAND_CONCAT_US(_1, VAR1(__VA_ARGS__)) #define VAR3(_1, ...) EXPAND_CONCAT_US(_1, VAR2(__VA_ARGS__)) #define VAR4(_1, ...) EXPAND_CONCAT_US(_1, VAR3(__VA_ARGS__)) #define VAR5(_1, ...) EXPAND_CONCAT_US(_1, VAR4(__VA_ARGS__)) #define GET_VAR(...) GET_ARGS(__VA_ARGS__, VAR5, VAR4, VAR3, VAR2, VAR1)(__VA_ARGS__)
    
© www.soinside.com 2019 - 2024. All rights reserved.