打印宏观值而不知道宏的数量
Print macro values without knowing the amount of macros
我有包括生成文件的代码(我不提前知道其内容),我和我的用户在上面有一个约定,我和我的用户同意如何创建此文件,以便我可以使用它。这个文件看起来像
#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.prepropessor来满足我们的循环需求。但是,生成的代码必须自行起作用。不幸的是,#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)
...voilà!
看到它活在coliru
上注意:COLIRU片段包括GCC和Clang的警告残疾人,警告我们可怜的PAL最令人沮丧的解析:(
我很久以前就遇到了相同的需求。
我的解决方案是使用预处理器,但不要获得"代码中的答案"。
例如,clang++ -dM -E test.cpp
将输出所有宏。(当时,我使用了gcc
,但是相同的技术适用于GCC,Clang和Visual Studio的Cl.exe ...编译器开关可能会有所不同。)
ahh,drat,还包括所有预定义的宏。
因此,我会生成我不在乎的预定义宏的"黑名单"文件,然后使用它来过滤这些结果(使用grep -v
)。
我遇到的另一个问题是,有时有人会 #undef IMPORTANT_MACRO
,然后在转储中被错过。对于那些不常见的情况... ,然后谋杀开始。
此答案是书面的,考虑了后续问题。
c 具有对通用编程的支持,通常会消除对预处理器的需求。在这种情况下,最好制作一组类型特征,声明需要处理的参数的属性,以减少预处理器到有条件汇编的作用(或者如果应该每次都应该生成此代码,则完全消除它):
enum class
t_Param
{
begin, a = begin, b, c, d, e, z, end
};
template<t_Param param, typename TEnabled = void> class
t_ParamIsEnabled final: public ::std::true_type
{};
template<t_Param param> class
t_ParamIsEnabled
<
param
, typename ::std::enable_if
<
(t_Param::end == param)
#ifndef A1
|| (t_Param::a == param)
#endif
#ifndef B2
|| (t_Param::b == param)
#endif
#ifndef C3
|| (t_Param::c == param)
#endif
#ifndef D4
|| (t_Param::d == param)
#endif
#ifndef E5
|| (t_Param::e == param)
#endif
>::type
> final: public ::std::false_type
{};
template<t_Param param> class
t_ParamTrait;
template<> class
t_ParamTrait<t_Param::a> final
{
public: static constexpr auto const & num{"1"};
public: static constexpr auto const & val{"A"};
};
template<> class
t_ParamTrait<t_Param::b> final
{
public: static constexpr auto const & num{"2"};
public: static constexpr auto const & val{"B"};
};
template<> class
t_ParamTrait<t_Param::c> final
{
public: static constexpr auto const & num{"3"};
public: static constexpr auto const & val{"C"};
};
template<> class
t_ParamTrait<t_Param::d> final
{
public: static constexpr auto const & num{"4"};
public: static constexpr auto const & val{"D"};
};
template<> class
t_ParamTrait<t_Param::e> final
{
public: static constexpr auto const & num{"5"};
public: static constexpr auto const & val{"E"};
};
template<> class
t_ParamTrait<t_Param::z> final
{
public: static constexpr auto const & num{"26"};
public: static constexpr auto const & val{"ZZ"};
};
这将允许您使用通用代码迭代参数并查询其属性:
template<t_Param param> typename ::std::enable_if<t_ParamIsEnabled<param>::value>::type
Echo(void)
{
::std::cout << t_ParamTrait<param>::val << ":" << t_ParamTrait<param>::num << ::std::endl;
}
template<t_Param param> typename ::std::enable_if<!t_ParamIsEnabled<param>::value>::type
Echo(void)
{
// Do nothing
}
template<int param_index = 0> void
Echo_All(void)
{
Echo<static_cast<t_Param>(param_index)>();
Echo_All<param_index + 1>();
}
template<> void
Echo_All<static_cast<int>(t_Param::end)>(void)
{
// Do nothing.
}
int main()
{
Echo_All();
return 0;
}
在线编译器
- 努力将整数转换为链表。不知道我在这里做错了什么
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 叮当不知道PTRDIFF_MAX?
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 我正在尝试使用 c++ 创建一个货币转换程序,我不知道如何继续
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 如何在C++中读取空格分隔的输入 当我们不知道输入的数量时
- 我不知道这条线是做什么的
- 如何在不知道C++中有多少可选参数的情况下在循环中使用va_arg?
- 在不知道套接字的情况下关闭网络连接
- 如果我不知道每个列表中有多少个数字,我如何将给定数量的数字列表作为输入?
- 我不知道导致错误的原因 (C3074)
- 我不知道为什么这段代码会让核心被转储?
- 我正在尝试制作一个自平衡机器人,但编译时存在错误。我不知道如何解决它
- 循环通过网格获取温度,但不知道如何告诉程序停止循环
- 如何在不知道对应关系的情况下在字符串中搜索字符并将其分配给另一个字符?
- 反转字符串.不知道为什么这个逻辑是错误的.C++
- 不知道如何在家庭作业任务中实现一件事
- 打印宏观值而不知道宏的数量