有没有办法添加或编辑assert引发的消息?我想使用类似在声明中添加自定义消息?
assert(a == b, "A must be equal to B");
然后,编译器添加线,时间等等...
这可能吗?
有没有办法添加或编辑assert引发的消息?我想使用类似在声明中添加自定义消息?
assert(a == b, "A must be equal to B");
然后,编译器添加线,时间等等...
这可能吗?
我见过的黑客是使用&&
运营商。由于指针“是真的”,如果它不为空,你可以做以下不改变的条件:
assert(a == b && "A is not equal to B");
由于assert
显示失败,它会显示你的消息太条件。如果这还不够,你可以编写自己的myAssert
函数或宏,它会显示你想要的。
断言是宏/功能组合。你可以定义自己的宏/功能,采用__FILE__
,__BASE_FILE__
,__LINE__
等,用自己的函数,它的自定义消息
另一种选择是扭转操作数和用逗号。你需要额外的括号以逗号不是参数之间的分隔符处理:
assert(("A must be equal to B", a == b));
(这是从上述意见复制,为更好的可视性)
这是一个很好的方法,当使用'-Wunused-value – v010dya 2016-01-30 11:02:57
或用宏编译时,它会显示“警告:逗号运算符的左操作数没有任何效果”,在g ++中编译时使用#ifndef m_assert #define m_assert(expr,msg)assert((msg,expr)) #endif – 2017-08-03 10:50:29
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
你可以直接使用它或复制Boost的代码。另外请注意Boost assert只是头文件,所以如果你不想安装所有的Boost,你可以只抓取那个文件。
对于VC,在ASSERT.H添加以下代码,
#define assert2(_Expression, _Msg) (void)((!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0))
修改你的编译器头文件是个坏主意。 – 2015-04-21 00:31:40
由于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");
的代码,即人类分析的条件。可读性。也不是一种语言破解。
“由于断言错误的读者将从错误消息中查找文件和行,” - 只有在他们勤奋的情况下。 – 2017-09-27 04:49:17
只有当他们想修复你的意思是......多么愚蠢的评论 – metamorphosis 2017-09-27 05:12:41
让人们看到问题越容易,他们就越有可能采取行动。 – 2017-09-27 15:51:15
为什么没有人提到最干净的解决方案?
bool AMustBeEqualToB = (a == b);
assert(AMustBeEqualToB);
如果评估的表达式不能被证明没有副作用(比如函数调用),那么这个方法会强制编译器包含评估,即使在一个发布版本中,断言将被忽略。至于“干净” - 代码看起来最好的是个人喜好,但我怀疑很多人会认为它比其旁边的评论更可读。 – 2015-09-14 00:19:38
但是,如果我们发表评论,断言失败后将不会在控制台上打印。 – 2015-09-14 12:08:53
是的,的确如此,但是 - 正如其他人所指出的那样 - 如果您断言失败,那么您首先要做的第一件事就是访问违规代码行。大多数情况下,除非您查看断言失败的上下文,否则您甚至不会知道“a”和“b”的含义,因此无论如何您必须访问代码。如果断言在没有代码见解的情况下应该是可以理解的,那么对于我来说,这将暗示您在这种情况下使用了错误的错误报告机制。 – 2015-09-15 00:14:16
这里是我的版本断言宏,它接受的消息,并以明确的方式打印的所有问题:
#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行
尼斯和清洁,随时在您的代码中使用它=)
不错的一个。非常有用 – Killrazor 2016-06-03 11:55:21
我有点困惑。 #Expr是否被视为直接替换的字符串? #Expr和Expr有什么区别? – 2016-09-22 17:25:30
@MinhTran让我们假设你的断言条件是'x == y'。然后Expr将展开为'if(!(x == y))',这是检查条件的地方,并且#Expr将展开为字符串文字'“x == y”',然后我们将其输入到错误消息中。 – 2016-10-14 07:27:57
您可以定义一个宏,如[this](http://stackoverflow.com/a/3767883/1070480)。 – HelloGoodbye 2015-12-18 12:02:39