如何用不同数量的信息参数编写一个c ++ assert宏? [英] How to write a c++ assert macro with a varying number of informational arguments?
问题描述
我想写一个类似于标准 assert
的宏 dbgassert
。除了 assert
,我想要 dbgassert
打印任意数量的附加参数(包含调试信息)。
I am trying to write a macro dbgassert
similar to the standard assert
. In addition to what assert
does, I want to dbgassert
print an arbitrary number of additional parameters (containing debugging information).
我到目前为止所列的是从此SO回答。但我有我的问题在我的代码与可变参数模板或宏。如果我使用至少一个附加参数(OK行),则 dbgassert
按预期工作。但是如果我没有额外的参数,那么编译失败(问题行)。
What I have so far is listed below, which is adapted from this SO answer. But I am having issue in my code with either variadic templates or macros. If I use at least one additional argument (the OK line), then dbgassert
works as expected. But if I give no additional argument, then compilation fails (the problem line).
我有一些变化模板编程的经验(如打印元组)我以前没有使用过可变宏。
I have some experience with variadic template programming (like how to print a tuple), but I haven't used variadic macros before.
有些人可以解释写这个可变参数宏组合的正确方法是什么?
Can some please explain what's the proper way of writing this variadic parameters macro combination?
顺便说一句,有人可以解释宏中的 #EX
魔法吗?它显示的表达式和工作对我在gcc4.8.1。是否受到普遍支持?
By the way, could someone explain the #EX
magic in the macro? It shows the expression and works for me on gcc4.8.1. Is it universally supported?
感谢,
//corrected reserved identifier issue and assumption issues per comments
#include <cassert>
#include <iostream>
using namespace std;
template <typename ...Args>
void realdbgassert(const char *msg, const char *file, int line, Args ... args) {
cout << "Assertion failed! \nFile " << file << ", Line " << line << endl
<< " Expression: " << msg << endl;
std::abort();
}
#define dbgassert(EX,...) \
(void)((EX) || (realdbgassert (#EX, __FILE__, __LINE__, __VA_ARGS__),0))
int main() {
dbgassert(1>2,"right","yes"); //OK
dbgassert(1>2,"right"); //OK.
//dbgassert(1>2); //Problem. compile error: expected primary-expression before ')' token
//#define dbgassert(EX,...) (void)((EX) || (realdbgassert (#EX, __FILE__, __LINE__, __VA_ARGS__)^,0))
}
Original version of the code.
#include <cassert>
#include <sstream>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
extern void __assert (const char *msg, const char *file, int line);
#ifdef __cplusplus
};
#endif
template <typename ...Args>
void _realdbgassert(const char *msg, const char *file, int line, Args ... args) {
stringstream os;
//... do something
__assert(msg,file,line);
}
#define dbgassert(EX,...) (void)((EX) || (_realdbgassert (#EX, __FILE__, __LINE__, __VA_ARGS__),0))
int main() {
dbgassert(1==0,"right"); //Problem line: undefined reference to `__assert'
}
推荐答案
您的问题是 __ VA_ARGS __
的值,在问题情况下为空。因此,当预处理器扩展 realdbgassert(#EX,__FILE__,__LINE__,__VA_ARGS __)
时,结果是未完成的参数列表 realdbgassert(1> 2 ,foo.c,42,)
。请注意,由于 __ VA_ARGS __
的空展开,参数列表未正确终止。
Your problem is the value of __VA_ARGS__
which is empty in the problem case. So, when the preprocessor expands realdbgassert(#EX, __FILE__, __LINE__, __VA_ARGS__)
, the result is an unfinished parameter list realdbgassert("1>2", "foo.c", 42, )
. Note that the parameter list is not correctly terminated due to the empty expansion of __VA_ARGS__
.
需要使用某种伎俩。最好的解决方案是,调整环境,使 __ VA_ARGS __
包括最后一个无条件参数,并在函数调用结束时与可选的参数一起传递。这是最好的,因为它是标准的C。
To fix this, you need to use some kind of trick. The best solution is, to tweak the circumstances so that __VA_ARGS__
includes the last unconditional argument, and pass that together with the optional ones at the end of the function call. This is best, because it's standard C.
我知道的另一个修复是对该语言的gcc扩展:见此 gcc文档页面了解更多详细信息,但您可以通过添加一个双 ##
在 __ VA_ARGS __
前面:
The other fix that I know of, is a gcc extension to the language: See this gcc documentation page for more detailed info, but you can fix your macro by adding a double ##
in front of __VA_ARGS__
:
#define dbgassert(EX,...) \
(void)((EX) || (realdbgassert (#EX, __FILE__, __LINE__, ## __VA_ARGS__),0))
Ps:
#
是预处理器的字符串化操作符:它将宏参数的值转换为字符串文字,i。 e。而不是粘贴 1> 2
它粘贴1> 2
。
Ps:
The #
is the stringification operator of the preprocessor: it turns the value of the macro parameter into a string literal, i. e. instead of pasting 1>2
it pastes "1>2"
.
这篇关于如何用不同数量的信息参数编写一个c ++ assert宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!