我的代码包含一个生成的文件(我事先不知道它的内容),只是一个约定,我和我的用户就如何创建此文件达成了共识,以便可以使用它。这个文件看起来像
#define MACRO0 "A"
#define MACRO1 "B"
#define MACRO2 "C"
...
我想打印所有宏值。我当前的代码看起来像
#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
我的问题是,如何遍历生成的文件中的宏,因此我不需要重复太多代码
首先,我们知道可以依靠Boost.Preprocessor满足我们的循环需求。但是,生成的代码必须独立运行。不幸的是,#ifdef
由于宏扩展而无法工作,因此无法生成问题中的代码。我们被敬酒了吗?
还没!我们可以利用您的宏都不存在或字符串文字的事实。考虑以下:
using StrPtr = char const *;
StrPtr probe(StrPtr(MACRO1));
我们在这里利用最老旧的语法来利用我们的老朋友。根据是否MACRO1
定义,可以用两种方式解释第二行。没有它,它等效于:
char const *probe(char const *MACRO1);
...这是一个函数声明,其中MACRO1
参数的名称。但是,当MACRO1
定义为时"B"
,它等效于:
char const *probe = (char const *) "B";
...这是一个初始化为指向的变量"B"
。然后,我们可以打开刚刚生成的内容的类型,以查看是否发生了替换:
if(!std::is_function<decltype(probe)>::value)
std::cout << "MACRO1 " << probe << '\n';
我们可以在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)
... 这里!
注意:Coliru代码段中包含针对GCC和Clang的警告禁用器,警告我们可怜的朋友最烦人的解析:(
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句