【发布时间】:2013-04-24 15:35:24
【问题描述】:
我有一些字符串我希望能够以符号方式使用,即好像我声明了一个宏
#define kBlahProperty "kBlahProperty"
#define kFooProperty "kFooProperty"
我不能使用枚举的原因有很多(有关更多上下文,请参阅previous question),例如在调试器中获取有用的信息、以可读格式序列化数据以及处理以不同方式定义的属性集源文件。
典型用法:
setProperty(kBlahProperty, 6);
if (otherProperty==kBlahProperty) { doStuff(); }
std::cout << "property type: " << kBlahProperty; // outputs "kBlahProperty" rather than an enum
这些属性可能有很多,为了便于定义,我希望能够像这样声明它们,只在一个地方:
DEFINE_PROPERTY(kBlahProperty)
DEFINE_PROPERTY(kFooProperty)
但是,我找不到定义宏的方法,该宏本身会扩展为#define(我尝试了几个使用 '#' 和 '##' 运算符的示例,但要粘贴 ' #define' 是问题)。
另一种方法是将要扩展的宏定义为char*:
#define DEFINE_PROPERTY(propName) const char8* propName=#propName
但这有一个问题,即它在每个编译单元中都被定义,因此出现链接器错误。如果我将其更改为使用extern,那么我无法将其定义为使用字符串本身——它必须放在 .cpp 文件中,所以现在我需要在标题中声明所有这些属性并再次定义它们在 cpp 文件中,因此您在两个地方都有一个列表。
那么有没有一种定义这些字符串的好方法,这样你就可以只声明它们一次?我可以使用 boost 预处理器,但只能使用 C++-0x 的一小部分(所以in-class constant initialisers 已经出局了)。
【问题讨论】:
-
既然您使用的是 C++,为什么不使用
std::string处理字符串呢?如果你使用指针(或数组)在比较中错误地切换了操作数的顺序,则无法进行比较之类的事情。 -
只是 FWIW,扩展为宏的宏无论如何都不会对您有任何好处:“生成的完全由宏替换的预处理令牌序列不会作为预处理指令处理,即使它类似于一个。 ..”
-
简单(如果丑陋)方式 - 仅在未定义另一个符号时定义宏以包含 extern,并在包含标头之前在一个编译单元中定义该符号
-
@JoachimPileborg:不使用
std::string的两个原因 - (1) 它仍然需要单独的声明和定义,就像char*所做的那样,以及 (2) 它必须是静态的常量,并且会冒着初始化问题的静态顺序的风险(即不能保证它会在其他可能引用它的东西之前构建) -
@JerryCoffin:我怀疑可能是这样
标签: c++ c-preprocessor