【发布时间】:2017-10-13 13:32:57
【问题描述】:
我有以下代码:
#define FOO_BAR x
#define FOO(x) FOO_BAR
我确实希望 FOO(2) 扩展到 2,但我得到的是 x。我尝试使用EXPAND 宏来强制进行额外扫描:
#define FOO_BAR x
#define EXPAND(x) x
#define FOO(x) EXPAND(FOO_BAR)
注意,这是故意的,FOO_BAR 不接受 x 作为参数。基本上,我不能将 x 传递给FOO_BAR。
但它也不起作用。有什么想法吗?
我希望它适用于任何编译器(MSVC、gcc、clang)。
我到底想要完成什么
我的最终目标是为 OpenGL 创建类型安全的枚举。所以,我需要从我的安全枚举映射到不安全的枚举。所以我有类似的东西:
enum class my_enum {
foo,
bar
}
GLenum my_enum2gl(my_enum e) {
switch (e) {
case my_enum::foo: return GL_FOO;
case my_enum::bar: return GL_BAR;
}
return GL_NONE;
}
由于我很懒,我做了一些preprocessor magic。并将其实现为:
#define PP_IMPL_ENUM_VALUE(enum_pair) __PP_EVAL(__PP_IMPL_ENUM_VALUE enum_pair)
#define __PP_IMPL_ENUM_VALUE(cpp_enum, gl_enum) cpp_enum,
#define PP_IMPL_CONVERT(enum_pair) __PP_EVAL(__PP_IMPL_CONVERT enum_pair)
#define __PP_IMPL_CONVERT(cpp_enum, gl_enum) case name::cpp_enum: return gl_enum;
#define DEF_STATE_ENUM(name, ...) \
enum name { \
PP_FOR_EACH(PP_IMPL_ENUM_VALUE, ##__VA_ARGS__) \
}; \
namespace detail { \
GLenum name ## 2gl(name e) { \
switch(e) { \
__PP_EVAL(PP_FOR_EACH(PP_IMPL_CONVERT, ##__VA_ARGS__)) \
default: \
assert(!"Unknown value"); \
return GL_NONE; \
} \
} \
}
DEF_STATE_ENUM(my_enum,
(foo, GL_FOO),
(bar, GL_BAR)
)
问题在于__PP_IMPL_CONVERT 使用了未展开的name。将x 传递给FOO_BAR 意味着我将一些额外的参数传递给PP_FOR_EACH 的函子。
【问题讨论】:
-
我唯一能建议的是使用一些外部预处理器。您不能在 C 中执行此操作。
-
你得到 x 因为那是你定义的 FOO_BAR 。您不能将无参数宏扩展为要作为参数传入的值。
-
C != C++。仅使用您正在使用的语言进行标记,除非两者确实相关。
-
@tambre,两者都是相关的,我很确定任何答案都适用于两种语言。
-
你的问题是问如何做一些不可能做的事情;
FOO中的x是一个参数(在参数替换期间扩展),FOO_BAR中的x是 justx,两者永远不会混合。 Boost 预处理器的FOR_EACH构造每个都采用非常适合此用例的数据参数。如果你有一个PP_FOR_EACH变体可以做到那个,你可以在这里使用它。你愿意只使用 boost 预处理器库吗?
标签: c++ c c-preprocessor