C++ 添加消息断言
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3767869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding message to assert
提问by tauran
Hallo!
你好!
I'm looking for a way to add custom messages to assert statements. I found this questions Add custom messages in assert?but the message is static there. I want to do something like this:
我正在寻找一种将自定义消息添加到断言语句的方法。我发现这个问题在断言中添加自定义消息?但消息在那里是静态的。我想做这样的事情:
assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));
When the assertion fails I want the normal output plus for example "x was 100".
当断言失败时,我想要正常输出加上例如“x 是 100”。
回答by Konrad Rudolph
You are out of luck here. The best way is to define your own assert
macro.
你在这里倒霉了。最好的方法是定义自己的assert
宏。
Basically, it can look like this:
基本上,它看起来像这样:
#ifndef NDEBUG
# define ASSERT(condition, message) \
do { \
if (! (condition)) { \
std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
<< " line " << __LINE__ << ": " << message << std::endl; \
std::terminate(); \
} \
} while (false)
#else
# define ASSERT(condition, message) do { } while (false)
#endif
This will define the ASSERT
macro only if the no-debug macro NDEBUG
isn't defined.
这将定义ASSERT
只有在没有调试宏宏NDEBUG
没有定义。
Then you'd use it like this:
然后你会像这样使用它:
ASSERT((0 < x) && (x < 10), "x was " << x);
Which is a bit simpler than your usage since you don't need to stringify "x was "
and x
explicitly, this is done implicitly by the macro.
这比您的用法简单一点,因为您不需要字符串化"x was "
和x
显式,这是由宏隐式完成的。
回答by Cameron
There are some old tricks to include messages without writing your own routines:
有一些古老的技巧可以在不编写自己的例程的情况下包含消息:
The first is this:
第一个是这样的:
bool testbool = false;
assert(("this is the time", testbool));
There is also:
还有:
bool testbool = false;
assert(testbool && "This is a message");
The first one works, because the inside parens expression result is the value of 'testbool'. The second one works, because the value of the string is going to be non-zero.
第一个有效,因为里面的括号表达式结果是'testbool'的值。第二个有效,因为字符串的值将是非零的。
回答by Alsk
A better alternative is to teach the debugger to stop on assert when it fails, then you could examine not only the x value but any other information including call stack. Perhaps, this is what you are really looking for. Sample implementation is mentioned here Ways to show your co-programmers that some methods are not yet implemented in a class when programming in C++
更好的选择是教调试器在断言失败时停止断言,然后您不仅可以检查 x 值,还可以检查任何其他信息,包括调用堆栈。也许,这就是您真正要寻找的。此处提到了示例实现向您的合作程序员展示某些方法在使用 C++ 编程时尚未在类中实现的方法
回答by AlcubierreDrive
#define ASSERT_WITH_MESSAGE(condition, message) do { \
if (!(condition)) { printf((message)); } \
assert ((condition)); } while(false)
回答by Gregory Pakosz
For the sake of completeness, I published a drop-in 2 files assert macro implementation in C++:
为了完整起见,我在 C++ 中发布了一个插入的 2 个文件 assert 宏实现:
#include <pempek_assert.h>
int main()
{
float min = 0.0f;
float max = 1.0f;
float v = 2.0f;
PEMPEK_ASSERT(v > min && v < max,
"invalid value: %f, must be between %f and %f", v, min, max);
return 0;
}
Will prompt you with:
将提示您:
Assertion 'v > min && v < max' failed (DEBUG)
in file e.cpp, line 8
function: int main()
with message: invalid value: 2.000000, must be between 0.000000 and 1.000000
Press (I)gnore / Ignore (F)orever / Ignore (A)ll / (D)ebug / A(b)ort:
Where
在哪里
- (I)gnore: ignore the current assertion
- Ignore (F)orever: remember the file and line where the assertion fired and ignore it for the remaining execution of the program
- Ignore (A)ll: ignore all remaining assertions (all files and lines)
- (D)ebug: break into the debugger if attached, otherwise
abort()
(on Windows, the system will prompt the user to attach a debugger) - A(b)ort: call
abort()
immediately
- (I)gnore:忽略当前断言
- Ignore (F)orever:记住断言触发的文件和行,并在程序的剩余执行过程中忽略它
- Ignore (A)ll:忽略所有剩余的断言(所有文件和行)
- (D)ebug:如果附加了就闯入调试器,否则
abort()
(在Windows上,系统会提示用户附加调试器) - A(b)ort:
abort()
立即调用
You can find out more about it there:
你可以在那里找到更多关于它的信息:
Hope that helps.
希望有帮助。
回答by solstice333
Extending on Kondrad Rudolph's answer:
扩展康德拉鲁道夫的回答:
#include <iostream>
#ifdef NDEBUG
#define assert(condition, message) 0
#else
#define assert(condition, message)\
(!(condition)) ?\
(std::cerr << "Assertion failed: (" << #condition << "), "\
<< "function " << __FUNCTION__\
<< ", file " << __FILE__\
<< ", line " << __LINE__ << "."\
<< std::endl << message << std::endl, abort(), 0) : 1
#endif
void foo() {
int sum = 0;
assert((sum = 1 + 1) == 3, "got sum of " << sum << ", but expected 3");
}
int main () {
foo();
}
Output is...
输出是...
Assertion failed: ((sum = 1 + 1) == 3), function foo, file foo.cpp, line 13.
got sum of 2, but expected 3
zsh: abort ./a.out
which is similar to what the std::assert macro outputs on my system just with the additional user defined message
这类似于 std::assert 宏在我的系统上输出的内容,只是附加了用户定义的消息
回答by Feng Wang
Yes, this is possible.
是的,这是可能的。
To enable expression like better_assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));
, we are supposed to have a corresponding macro in a form of
要启用类似的表达式better_assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));
,我们应该有一个相应的宏,其形式为
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? \
(void)0 : print_assertion(std::cerr, \
"Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, \
" in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
in which print_assertion
is a proxy function to do the assertion. When the EXPRESSION
is evaluated false
, all the debug information, the __VA_ARGS__
, will be dumped to std::cerr
. This function takes arbitrary numbers of arguments, thus we should implement a variadic templated function:
其中print_assertion
是执行断言的代理函数。当EXPRESSION
评估false
,所有调试信息的__VA_ARGS__
,将被转储到std::cerr
。这个函数接受任意数量的参数,因此我们应该实现一个可变参数模板函数:
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
out.precision( 20 );
if constexpr( debug_mode )
{
(out << ... << args) << std::endl;
abort();
}
}
In the previous implementation, the expression (out << ... << args) << std::endl;
make use of fold expression in C++17 (https://en.cppreference.com/w/cpp/language/fold); the constant expression debug_mode
is related to the compilation options passed, which is can be defined as
在前面的实现中,表达式(out << ... << args) << std::endl;
使用了 C++17 中的折叠表达式(https://en.cppreference.com/w/cpp/language/fold);常量表达式debug_mode
与传递的编译选项有关,可以定义为
#ifdef NDEBUG
constexpr std::uint_least64_t debug_mode = 0;
#else
constexpr std::uint_least64_t debug_mode = 1;
#endif
It also worth mentioning that the expression if constexpr( debug_mode )
makes use of constexpr if (https://en.cppreference.com/w/cpp/language/if) imported since C++17.
还值得一提的是,该表达式if constexpr( debug_mode )
使用了自 C++17 以来导入的 constexpr if ( https://en.cppreference.com/w/cpp/language/if)。
To wrap everything up, we have:
总结一下,我们有:
#ifdef NDEBUG
constexpr std::uint_least64_t debug_mode = 0;
#else
constexpr std::uint_least64_t debug_mode = 1;
#endif
template< typename... Args >
void print_assertion(std::ostream& out, Args&&... args)
{
out.precision( 20 );
if constexpr( debug_mode )
{
(out << ... << args) << std::endl;
abort();
}
}
#ifdef better_assert
#undef better_assert
#endif
#define better_assert(EXPRESSION, ... ) ((EXPRESSION) ? (void)0 : print_assertion(std::cerr, "Assertion failure: ", #EXPRESSION, " in File: ", __FILE__, " in Line: ", __LINE__ __VA_OPT__(,) __VA_ARGS__))
A typical test case demonstrating its usage can be:
展示其用法的典型测试用例可以是:
double const a = 3.14159265358979;
double const b = 2.0 * std::asin( 1.0 );
better_assert( a==b, " a is supposed to be equal to b, but now a = ", a, " and b = ", b );
This will produce something error message like:
这将产生一些错误信息,如:
Assertion failure: a==b in File: test.cc in Line: 9 a is supposed to be equal to b, but now a = 3.1415926535897900074 and b = 3.141592653589793116
[1] 8414 abort (core dumped) ./test
And the full source code is available in this repo: https://github.com/fengwang/better_assert
完整源代码可在此 repo 中找到:https: //github.com/fengwang/better_assert
回答by Austin_Anderson
going along with Konrad Rudolf's answer you can do it a bit more concise with
与康拉德鲁道夫的回答一起,你可以更简洁地使用
#include <assert.h>
#include <stdio.h>
#define ASSERT(condition,...) assert( \
condition|| \
(fprintf(stderr,__VA_ARGS__)&&fprintf(stderr," at %s:%d\n",__FILE__,__LINE__)) \
);
which also works in C,
这也适用于C,
it works using the general idea from some of the answers to the question you linked, but the macro allows it to be a little more flexible
它使用您链接的问题的一些答案中的一般思想来工作,但是宏使它变得更加灵活