在不知道宏数量的情况下打印宏值 [英] Print macro values without knowing the amount of macros

查看:92
本文介绍了在不知道宏数量的情况下打印宏值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有包含生成文件的代码(我不知道其内容),只是我和我的用户就如何创建此文件达成了一项约定,以便我可以使用它。该文件看起来像

I have code that includes a generated file (I don't know in advance its content), there is just a convention upon which me and my users agreed on how to create this file so I can use it. This file looks like

#define MACRO0 "A"
#define MACRO1 "B"
#define MACRO2 "C"
...

我要打印所有宏值。我当前的代码如下:

I want to print all macros values. My current code looks like

#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

我的问题是,如何遍历所生成文件中的宏,因此我不需要重复太多代码

My question is, how to iterate over the macros in the generated file so I don't need to duplicate my code so much

推荐答案

首先,我们知道我们可以依靠Boost.Preprocessor我们的循环需求。但是,生成的代码必须独立运行。不幸的是, #ifdef 由于宏扩展而无法工作,因此无法生成问题中的代码。我们敬酒了吗?

First of all, we know we can count on Boost.Preprocessor for our looping needs. However, the generated code must work on its own. Unfortunately, #ifdef cannot work as a result of macro expansion, so there's no way to generate the code in your question. Are we toasted?

还没有!我们可以利用您的宏都不存在或字符串文字的事实。考虑以下内容:

Not yet! We can take advantage of the fact that your macros are all either nonexistent or a string literal. Consider the following:

using StrPtr = char const *;
StrPtr probe(StrPtr(MACRO1));

我们在这里利用最老旧的语法来利用我们的老朋友。根据是否定义了 MACRO1 ,可以用两种方式解释第二行。没有它,它等效于:

We're taking advantage of our old friend the most vexing parse here. The second line can be interpreted in two ways depending on whether MACRO1 is defined. Without it, it is equivalent to:

char const *probe(char const *MACRO1);

...这是一个函数声明,其中 MACRO1 是参数的名称。但是,当 MACRO1 被定义为 B 时,它等效于:

... which is a function declaration where MACRO1 is the name of the parameter. But, when MACRO1 is defined to be "B", it becomes equivalent to:

char const *probe = (char const *) "B";

...这是一个初始化为指向 B 。然后,我们可以打开刚刚生成的内容的类型,以查看是否发生了替换:

... which is a variable initialized to point at "B". We can then switch on the type of what we just produced to see if a substitution occured:

if(!std::is_function<decltype(probe)>::value)
    std::cout << "MACRO1 " << probe << '\n';

如果在此处使用constexpr ,我们可以使用 ,但是 std :: cout 可以输出函数指针(它将其转换为 bool ),因此无效分支有效

We could make use of if constexpr here, but std::cout can output a function pointer (it converts it to bool) so the dead branch is valid, and the compiler is clever enough to completely optimize it out.

最后,我们回到Boost.Preprocessor为我们生成所有这些东西:

Finally, we come back to Boost.Preprocessor to generate all that stuff for us:

#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)

...voilà!

在Coliru上实时查看

注意:Coliru代码段中包含针对GCC和Clang的警告禁用项,警告我们可怜的朋友最烦人的解析:(

Note: the Coliru snippet includes warning disablers for GCC and Clang, which warn against our poor pal the most vexing parse :(

这篇关于在不知道宏数量的情况下打印宏值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆