在assert中添加自定义消息?

Kil*_*zor 114 c++ assert

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

assert(a == b, "A must be equal to B");
Run Code Online (Sandbox Code Playgroud)

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

可能吗?

zne*_*eak 219

我见过的黑客是使用&&运营商.如果指针"为真",如果它为非空,则可以在不改变条件的情况下执行以下操作:

assert(a == b && "A is not equal to B");
Run Code Online (Sandbox Code Playgroud)

由于assert显示失败的条件,它也会显示您的消息.如果还不够,你可以编写自己的myAssert函数或宏来显示你想要的任何东西.

  • 另一种选择是反转操作数并使用逗号运算符.你需要额外的括号,所以逗号不被视为参数之间的分隔符:`assert(("A必须等于B",a == b)); (24认同)
  • @Frank,`printf`如果打印任何东西,则返回一个非零值,所以你可以做`assert(a == b && printf("a(%i)不等于b(%i)"), a,b))`,虽然在那一点上你应该编写自己的断言包装器. (6认同)
  • 不过,能够打印变量的值也很好,例如:`assert(a == b &&“ A(” << A <<“)不等于B(” << B < <“)”);` (2认同)
  • 糟糕的代码!我不明白这个!如果 a==b 为 false,则 and 表达式也应为 false,因此不应计算字符串。 (2认同)
  • @TUIlover,这不是 C 字符串文字的工作方式;它们是编译时常量,并且它们在这种情况下的使用被简单地优化掉了。没有运行时成本。 (2认同)

And*_*tan 40

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

assert(("A must be equal to B", a == b));
Run Code Online (Sandbox Code Playgroud)

(这是从上面的评论中复制的,以获得更好的可见性)

  • 这是一个很好的方法,只有一个很小的问题,它会显示"警告:逗号运算符的左操作数没有效果",当使用`-Wunused-value在g ++中编译时 (2认同)
  • 或使用宏: #ifndef m_assert #define m_assert(expr, msg) assert((msg, expr)) #endif (2认同)
  • 使用宏包装器可以避免 gcc 警告:`#define m_assert(expr, msg) assert(( (void)(msg), (expr) ))` (2认同)

小智 20

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

#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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用它

M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
Run Code Online (Sandbox Code Playgroud)

如果失败,您将收到如下消息:

断言失败:MyFunction:需要非null参数

预期:ptr!= nullptr

来源:C:\ MyProject\src.cpp,第22行

很好,干净,随意在你的代码中使用=)


Zer*_*ero 18

BOOST_ASSERT_MSG(expre, msg)
Run Code Online (Sandbox Code Playgroud)

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

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


met*_*sis 7

由于zneak的回答在某种程度上使代码回旋,更好的方法是仅仅评论您正在谈论的字符串文本.即:

assert(a == b); // A must be equal to B
Run Code Online (Sandbox Code Playgroud)

由于断言错误的读者将从错误消息中查找文件和行,因此他们将在此处看到完整的解释.

因为,在一天结束时,这:

assert(number_of_frames != 0); // Has frames to update
Run Code Online (Sandbox Code Playgroud)

读取比这更好:

assert(number_of_frames != 0 && "Has frames to update");
Run Code Online (Sandbox Code Playgroud)

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

  • 不会。你越容易让人们看到问题,他们就越有可能采取行动。 (5认同)