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

发布于 2024-09-18 09:00:06 字数 161 浏览 4 评论 0原文

有没有办法添加或编辑断言抛出的消息?我想使用类似的东西

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

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

这可能吗?

Is there a way to add or edit the message thrown by assert? I'd like to use something like

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

Then, the compiler adds line, time and so on...

Is it possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

神经大条 2024-09-25 09:00:06

我见过的一个技巧是使用 && 运算符。由于指针如果非空则“为真”,因此您可以在不更改条件的情况下执行以下操作:

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

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

A hack I've seen around is to use the && operator. Since a pointer "is true" if it's non-null, you can do the following without altering the condition:

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

Since assert shows the condition that failed, it will display your message too. If it's not enough, you can write your own myAssert function or macro that will display whatever you want.

戏舞 2024-09-25 09:00:06

另一种选择是反转操作数并使用逗号运算符。您需要额外的括号,以便逗号不会被视为参数之间的分隔符:(

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

这是从上面的注释复制的,以获得更好的可见性)

Another option is to reverse the operands and use the comma operator. You need extra parentheses so the comma isn't treated as a delimiter between the arguments:

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

(this was copied from above comments, for better visibility)

爱格式化 2024-09-25 09:00:06

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

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

漂亮干净,请随意在代码中使用它 =)

Here's my version of assert macro, which accepts the message and prints everything out in a clear way:

#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();
    }
}

Now, you can use this

M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");

And in case of failure you will get a message like this:

Assert failed:  MyFunction: requires non-null argument

Expected: ptr != nullptr

Source: C:\MyProject\src.cpp, line 22

Nice and clean, feel free to use it in your code =)

倥絔 2024-09-25 09:00:06
BOOST_ASSERT_MSG(expre, msg)

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

您可以直接使用它或复制 Boost 的代码。另请注意,Boost 断言只是标头,因此如果您不想安装所有 Boost,则可以只获取该单个文件。

BOOST_ASSERT_MSG(expre, msg)

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

You could either use that directly or copy Boost's code. Also note Boost assert is header only, so you could just grab that single file if you didn't want to install all of Boost.

固执像三岁 2024-09-25 09:00:06

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

就人类对代码的解析而言 。可读性。也不是语言黑客。

As zneak's answer convolutes the code somewhat, a better approach is to merely comment the string text you're talking about. ie.:

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

Since the reader of the assert error will look up the file and line anyway from the error message, they will see the full explanation here.

Because, at the end of the day, this:

assert(number_of_frames != 0); // Has frames to update

reads better than this:

assert(number_of_frames != 0 && "Has frames to update");

in terms of human parsing of code ie. readability. Also not a language hack.

天赋异禀 2024-09-25 09:00:06

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

assert is a macro/function combination. you can define your own macro/function, using __FILE__, __BASE_FILE__, __LINE__ etc, with your own function that takes a custom message

自此以后,行同陌路 2024-09-25 09:00:06

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

例如:

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

If the assert is done within a class, an alternative approach is to call a static predicate function with a self-describing name. If the assertion fails, the message will already contain the predicate's pretty and self-describing name.

E.g.:

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));
    // ...
}

You may even want to make that predicate function public so that the class' user can verify the precondition themselves.

Even if assert is not disabled for release builds, the compiler will likely inline the predicate if it's fairly trivial.

The same approach can be used for complex if conditions needing a comment. Instead of a comment, just call a self-describing predicate function.

看透却不说透 2024-09-25 09:00:06

您也可以编写自己的自定义断言函数。一个非常简单的示例:

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 和 j 应该相等”)

You could also just write your own custom assert function. A very simple example:

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;
}

play with the code.

The assertion reads Assertion print_if_false(i == j, "i and j should be equal").

回梦 2024-09-25 09:00:06
int x=10, y=25;
assert(x > y);   // Add message along with this assert

选项 1)由于 fprintf 返回打印的字符数,因此我们可以使用 !fprintf 或断言表达式。此处使用 stderr,因为这是一条错误消息

assert((x > y) || !fprintf(stderr, "Error: x %d is expected to be greater than y %d \n", x, y));

我们可以将其包装在宏中以方便使用。

// Define macro over assert
#define assert_msg(cond, fmt, ...) assert( cond || !fprintf(stderr, fmt, ##__VA_ARGS__))
// Use above macro
assert_msg(x > y, "Error: x %d is expected to be greater than y %d \n", x, y);

选项 2) 定义包含在 lambda 内的错误消息。

auto err =  [x, y] { fprintf(stderr, "Error: x %d should be greater than y %d \n", x, y); return false; };
assert((x > y) || err());   // Assert calls lambda func only when condition fails

这是转储的消息。

Error: x 10 should be greater than y 25 
File.cpp:10: int main(): Assertion `(x > y) || err()' failed.

选项 3) 或者我们可以改进上述解决方案,借助立即调用的 lambda 在一行中完成此操作

assert((x > y) || ([x, y] { fprintf(stderr, "Error: x %d is expected to be greater than y %d \n", x, y); return false; }()));
int x=10, y=25;
assert(x > y);   // Add message along with this assert

Option 1) Since fprintf returns number of characters printed so we can or assert expression with !fprintf. Using stderr here since this is an error message

assert((x > y) || !fprintf(stderr, "Error: x %d is expected to be greater than y %d \n", x, y));

We can wrap this inside a macro for convinient use.

// Define macro over assert
#define assert_msg(cond, fmt, ...) assert( cond || !fprintf(stderr, fmt, ##__VA_ARGS__))
// Use above macro
assert_msg(x > y, "Error: x %d is expected to be greater than y %d \n", x, y);

Option 2) Define error message wrapped inside lambda.

auto err =  [x, y] { fprintf(stderr, "Error: x %d should be greater than y %d \n", x, y); return false; };
assert((x > y) || err());   // Assert calls lambda func only when condition fails

Here is the dumped message.

Error: x 10 should be greater than y 25 
File.cpp:10: int main(): Assertion `(x > y) || err()' failed.

Option 3) Or we can refine above solution to do it in one line with help of immediately invoked lambda

assert((x > y) || ([x, y] { fprintf(stderr, "Error: x %d is expected to be greater than y %d \n", x, y); return false; }()));
萌辣 2024-09-25 09:00:06

@Shakti Malik,非常感谢您的解决方案!

我已将其简化为:

#define ASSERT(cond, msg, args...) assert((cond) || !fprintf(stderr, (msg "\n"), args))

优秀作品)

@Shakti Malik, thank you very much for your solution!

I have reduced it to:

#define ASSERT(cond, msg, args...) assert((cond) || !fprintf(stderr, (msg "\n"), args))

Excellent works)

当爱已成负担 2024-09-25 09:00:06

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

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

For vc, add following code in assert.h,

#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文