在断言中添加自定义消息?

有没有一种方法来添加或编辑由断言抛出的消息

assert(a == b, "A must be equal to B");

然后,编译器添加 台词时间等..。

有可能吗?

100426 次浏览

我见过的一种黑客行为是使用 &&操作员。因为如果指针是非空的,那么它就是真的,所以您可以在不改变条件的情况下执行以下操作:

assert(a == b && "A is not equal to B");

由于 assert显示了失败的条件,它也将显示您的消息。如果这还不够,您可以编写自己的 myAssert函数或宏来显示您想要的任何内容。

断言是宏/函数的组合。您可以使用 __FILE____BASE_FILE____LINE__等定义自己的宏/函数,并使用自己的函数接收自定义消息

另一种选择是反转操作数并使用逗号运算符。你需要额外的括号,这样逗号就不会被当作参数之间的分隔符:

assert(("A must be equal to B", a == b));

(这是从上面的评论中复制的,以便更好地显示)

BOOST_ASSERT_MSG(expre, msg)

Http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html

您可以直接使用它,也可以复制 Boost 的代码。还要注意的是,Boost 断言只是头文件,所以如果不想安装所有的 Boost,可以直接抓取这个文件。

对于 vc,在 assert.h 中添加以下代码,

#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )

由于 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");

在人类解析方面的代码,即可读性。也不是一个语言黑客。

下面是我的断言宏版本,它接受消息并以清晰的方式打印出所有内容:

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

干净漂亮,可以在代码中使用

你也可以编写自己的自定义断言函数,一个非常简单的例子:

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

如果断言是在类中完成的,另一种方法是使用自描述名称调用静态谓词函数。如果断言失败,消息将已经包含断言的漂亮和自我描述的名称。

例如:

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条件。不需要注释,只需调用自描述谓词函数即可。