e27*_*314 30 c++ c-preprocessor
我的代码包含一个生成的文件(我事先不知道它的内容),只有一个约定我和我的用户就如何创建这个文件达成一致,所以我可以使用它.这个文件看起来像
#define MACRO0 "A"
#define MACRO1 "B"
#define MACRO2 "C"
...
Run Code Online (Sandbox Code Playgroud)
我想打印所有宏值.我目前的代码看起来像
#ifdef MACRO0
std::cout << "MACRO0 " << MACRO0 << std::endl;
#endif
#ifdef MACRO1
std::cout << "MACRO1 " << MACRO1 << std::endl;
#endif
#ifdef MACRO2
std::cout << "MACRO2 " << MACRO2 << std::endl;
#endif
Run Code Online (Sandbox Code Playgroud)
我的问题是,如何迭代生成的文件中的宏,所以我不需要复制我的代码
Que*_*tin 52
首先,我们知道我们可以依靠Boost.Preprocessor来满足我们的循环需求.但是,生成的代码必须单独工作.遗憾的是,#ifdef由于宏扩展无法工作,因此无法在您的问题中生成代码.我们烤了吗?
还没!我们可以利用您的宏都不存在或字符串文字这一事实.考虑以下:
using StrPtr = char const *;
StrPtr probe(StrPtr(MACRO1));
Run Code Online (Sandbox Code Playgroud)
我们正在利用我们的老朋友这里最令人烦恼的解析.第二行可以用两种方式解释,具体取决于是否MACRO1定义.没有它,它相当于:
char const *probe(char const *MACRO1);
Run Code Online (Sandbox Code Playgroud)
...这是一个函数声明,其中MACRO1是参数的名称.但是,当MACRO1定义为时"B",它变得等同于:
char const *probe = (char const *) "B";
Run Code Online (Sandbox Code Playgroud)
...这是一个初始化为指向的变量"B".然后我们可以打开我们刚刚生成的类型,看看是否发生了替换:
if(!std::is_function<decltype(probe)>::value)
std::cout << "MACRO1 " << probe << '\n';
Run Code Online (Sandbox Code Playgroud)
我们可以使用if constexpr这里,但std::cout可以输出一个函数指针(它将其转换为bool),因此死分支是有效的,编译器足够聪明,可以完全优化它.
最后,我们回到Boost.Preprocessor为我们生成所有内容:
#define PRINT_IF_DEFINED(z, n, data) \
{ \
StrPtr probe(StrPtr(BOOST_PP_CAT(MACRO, n))); \
if(!std::is_function<decltype(probe)>::value) \
std::cout << "MACRO" BOOST_PP_STRINGIZE(n) " " << probe << '\n'; \
}
#define PRINT_MACROS(num) \
do { \
using StrPtr = char const *; \
BOOST_PP_REPEAT(num, PRINT_IF_DEFINED, ~) \
} while(false)
Run Code Online (Sandbox Code Playgroud)
......瞧!
注意:Coliru片段包含GCC和Clang的警告禁用,它警告我们可怜的朋友最烦恼的解析:(
| 归档时间: |
|
| 查看次数: |
828 次 |
| 最近记录: |