【发布时间】:2010-09-11 22:39:24
【问题描述】:
有没有办法添加或编辑断言抛出的消息?我想使用类似的东西
assert(a == b, "A must be equal to B");
然后,编译器添加line、time等...
有可能吗?
【问题讨论】:
-
你可以定义一个宏,比如this。
有没有办法添加或编辑断言抛出的消息?我想使用类似的东西
assert(a == b, "A must be equal to B");
然后,编译器添加line、time等...
有可能吗?
【问题讨论】:
我见过的一个技巧是使用&& 运算符。由于如果指针不为空,则“为真”,因此您可以在不改变条件的情况下执行以下操作:
assert(a == b && "A is not equal to B");
由于assert 显示失败的条件,它也会显示您的消息。如果还不够,您可以编写自己的 myAssert 函数或宏来显示您想要的任何内容。
【讨论】:
assert(("A must be equal to B", a == b));
assert(a == b && "A (" << A << ") is not equal to B (" << B << ")");
printf 如果打印任何内容,则返回非零值,因此您可以执行assert(a == b && printf("a (%i) is not equal to b (%i)", a, b)) 之类的操作,尽管此时您可能应该编写自己的断言包装器。跨度>
另一种选择是反转操作数并使用逗号运算符。您需要额外的括号,因此逗号不会被视为参数之间的分隔符:
assert(("A must be equal to B", a == b));
(这是从上面的 cmets 复制的,为了更好的可见性)
【讨论】:
#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))
这是我的断言宏版本,它接受消息并以清晰的方式打印出所有内容:
#include <iostream>
#ifndef NDEBUG
# define M_Assert(Expr, Msg) \
__M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
# define M_Assert(Expr, Msg) ;
#endif
void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
if (!expr)
{
std::cerr << "Assert failed:\t" << msg << "\n"
<< "Expected:\t" << expr_str << "\n"
<< "Source:\t\t" << file << ", line " << line << "\n";
abort();
}
}
现在,你可以使用它了
M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
如果失败,您将收到如下消息:
断言失败:MyFunction:需要非空参数
预期:ptr != nullptr
来源:C:\MyProject\src.cpp,第 22 行
又好又干净,您可以随意在您的代码中使用它 =)
【讨论】:
x == y。然后,Expr 将扩展为if( !(x == y)),这是检查条件的地方,而#Expr 将扩展为字符串文字"x == y",然后我们将其放入错误消息中。
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
您可以直接使用它,也可以复制 Boost 的代码。另请注意,Boost 断言只是标题,因此如果您不想安装所有 Boost,则可以只获取该单个文件。
【讨论】:
由于 zneak 的回答使代码有些复杂,因此更好的方法是仅注释您正在谈论的字符串文本。即:
assert(a == b); // A must be equal to B
由于断言错误的读者会从错误消息中查找文件和行,因此他们将在此处看到完整的解释。
因为,归根结底,这是:
assert(number_of_frames != 0); // Has frames to update
比这更好读:
assert(number_of_frames != 0 && "Has frames to update");
就人类对代码的解析而言,即。可读性。也不是语言黑客。
【讨论】:
assert 是一个宏/函数组合。您可以使用__FILE__、__BASE_FILE__、__LINE__ 等定义自己的宏/函数,并使用您自己的接收自定义消息的函数
【讨论】:
如果断言是在一个类中完成的,另一种方法是调用具有自描述名称的静态谓词函数。如果断言失败,则消息将已经包含谓词的漂亮和自描述名称。
例如:
static bool arguments_must_be_ordered(int a, int b) {return a <= b;}
void foo(int a, int b)
{
assert(arguments_must_be_ordered(a, b));
// ...
}
您甚至可能希望公开该谓词函数,以便该类的用户可以自己验证前提条件。
即使 assert 没有为发布版本禁用,编译器也可能会内联谓词,如果它相当简单的话。
同样的方法可用于需要注释的复杂if 条件。无需注释,只需调用自描述谓词函数即可。
【讨论】:
您也可以编写自己的自定义断言函数。一个很简单的例子:
bool print_if_false(const bool assertion, const char* msg) {
if(!assertion) {
// endl to flush
std::cout << msg << std::endl;
}
return assertion;
}
int main()
{
int i = 0;
int j = 1;
assert(print_if_false(i == j, "i and j should be equal"));
return 0;
}
断言为Assertion print_if_false(i == j, "i and j should be equal")。
【讨论】:
对于vc,在assert.h中添加如下代码,
#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )
【讨论】: