"Unpacking" 个宏参数
"Unpacking" macro arguments
我有以下宏:
#define HEX 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
#define BITS 0x01
#define ADD_FLAGS(a, b, c, d, e, f, g, h) \
a, b | BITS, c, d, e, f, g, h
我在某处使用它来创建一个字节数组{ADD_FLAGS(HEX)}
。这是行不通的。 HEX
被解释为 ADD_FLAGS
的单个参数,我得到的错误是参数太少。
const myStructure Table[ENTRY_COUNT] =
{
/* Entity Index 0 */
{
<some structure fields>,
ADD_FLAGS(HEX), // 8-byte array
<more structure fields>
}
}
我也尝试了以下变体,但没有成功:
#define EXPAND(x) x
#define ADD_FL(a, b, c, d, e, f, g, h) \
a, b | BITS, c, d, e, f, g, h
#define ADD_FLAGS(...) ADD_FL EXPAND((__VA_ARGS__))
##################### other variant
#define ADD_FLAGS(...) EXPAND(ADD_FL (__VA_ARGS__))
我正在使用 C99 和三种不同的编译器,所以任何答案都必须符合标准,否则肯定会有一个编译器不起作用(我正在使用 armclang、ghs 和 tasking)。
我建议您谨慎使用宏。这是一个示例代码段,它完全符合宏的功能,但在我看来它更合理一些。
template<typename ... Ts>
constexpr auto add_flags(Ts && ... args){
std::array flags{std::forward<Ts>(args)...};
constexpr int bits = 0x01;
// flags[some_idx] |= bits;
return flags;
}
抛开强制性的“避免使用宏”,您只需要将 ADD_FLAGS
包装在另一个宏中即可。
将其重命名为其他名称,例如ADD_FLAGS_
,并添加
#define ADD_FLAGS(...) ADD_FLAGS_(__VA_ARGS__)
这适用于 GCC 和 Clang。在 MSVC 中,这仅适用于新的预处理器(/Zc:preprocessor
标志)。
不确定如何使用旧的 MSVC 预处理器执行此操作,但由于它的错误众所周知,我会尽可能避免支持它。
我有以下宏:
#define HEX 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
#define BITS 0x01
#define ADD_FLAGS(a, b, c, d, e, f, g, h) \
a, b | BITS, c, d, e, f, g, h
我在某处使用它来创建一个字节数组{ADD_FLAGS(HEX)}
。这是行不通的。 HEX
被解释为 ADD_FLAGS
的单个参数,我得到的错误是参数太少。
const myStructure Table[ENTRY_COUNT] =
{
/* Entity Index 0 */
{
<some structure fields>,
ADD_FLAGS(HEX), // 8-byte array
<more structure fields>
}
}
我也尝试了以下变体,但没有成功:
#define EXPAND(x) x
#define ADD_FL(a, b, c, d, e, f, g, h) \
a, b | BITS, c, d, e, f, g, h
#define ADD_FLAGS(...) ADD_FL EXPAND((__VA_ARGS__))
##################### other variant
#define ADD_FLAGS(...) EXPAND(ADD_FL (__VA_ARGS__))
我正在使用 C99 和三种不同的编译器,所以任何答案都必须符合标准,否则肯定会有一个编译器不起作用(我正在使用 armclang、ghs 和 tasking)。
我建议您谨慎使用宏。这是一个示例代码段,它完全符合宏的功能,但在我看来它更合理一些。
template<typename ... Ts>
constexpr auto add_flags(Ts && ... args){
std::array flags{std::forward<Ts>(args)...};
constexpr int bits = 0x01;
// flags[some_idx] |= bits;
return flags;
}
抛开强制性的“避免使用宏”,您只需要将 ADD_FLAGS
包装在另一个宏中即可。
将其重命名为其他名称,例如ADD_FLAGS_
,并添加
#define ADD_FLAGS(...) ADD_FLAGS_(__VA_ARGS__)
这适用于 GCC 和 Clang。在 MSVC 中,这仅适用于新的预处理器(/Zc:preprocessor
标志)。
不确定如何使用旧的 MSVC 预处理器执行此操作,但由于它的错误众所周知,我会尽可能避免支持它。