2010-09-11 31 views
88

有没有办法添加或编辑assert引发的消息?我想使用类似在声明中添加自定义消息?

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

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

这可能吗?

+0

您可以定义一个宏,如[this](http://stackoverflow.com/a/3767883/1070480)。 – HelloGoodbye 2015-12-18 12:02:39

回答

169

我见过的黑客是使用&&运营商。由于指针“是真的”,如果它不为空,你可以做以下不改变的条件:

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

由于assert显示失​​败,它会显示你的消息太条件。如果这还不够,你可以编写自己的myAssert函数或宏,它会显示你想要的。

+4

Jaja!精美的一段代码。真的有用!谢谢! – Killrazor 2010-09-11 23:18:29

+1

@Killrazor如果解决了您的问题,请考虑通过点击旁边的复选标记将答案标记为“接受”。 :) – zneak 2010-09-11 23:21:30

+15

另一种选择是颠倒操作数并使用逗号运算符。你需要额外的括号,所以逗号不会被当作参数之间的分隔符:'assert((“A must be equal to B”,a == b));' – 2012-01-08 06:16:52

1

断言是宏/功能组合。你可以定义自己的宏/功能,采用__FILE____BASE_FILE____LINE__等,用自己的函数,它的自定义消息

21

另一种选择是扭转操作数和用逗号。你需要额外的括号以逗号不是参数之间的分隔符处理:

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

(这是从上述意见复制,为更好的可视性)

+1

这是一个很好的方法,当使用'-Wunused-value – v010dya 2016-01-30 11:02:57

+0

或用宏编译时,它会显示“警告:逗号运算符的左操作数没有任何效果”,在g ++中编译时使用#ifndef m_assert #define m_assert(expr,msg)assert((msg,expr)) #endif – 2017-08-03 10:50:29

15
BOOST_ASSERT_MSG(expre, msg) 

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

你可以直接使用它或复制Boost的代码。另外请注意Boost assert只是头文件,所以如果你不想安装所有的Boost,你可以只抓取那个文件。

+0

note boost需要你实现assert接口。 – Jichao 2013-10-29 04:54:57

+0

@Jichao,通过实现assert接口是什么意思? – Tarc 2016-08-22 21:57:04

-4

对于VC,在ASSERT.H添加以下代码,

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

修改你的编译器头文件是个坏主意。 – 2015-04-21 00:31:40

8

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

的代码,即人类分析的条件。可读性。也不是一种语言破解。

+0

“由于断言错误的读者将从错误消息中查找文件和行,” - 只有在他们勤奋的情况下。 – 2017-09-27 04:49:17

+0

只有当他们想修复你的意思是......多么愚蠢的评论 – metamorphosis 2017-09-27 05:12:41

+0

让人们看到问题越容易,他们就越有可能采取行动。 – 2017-09-27 15:51:15

0

为什么没有人提到最干净的解决方案?

bool AMustBeEqualToB = (a == b); 
assert(AMustBeEqualToB); 
+5

如果评估的表达式不能被证明没有副作用(比如函数调用),那么这个方法会强制编译器包含评估,即使在一个发布版本中,断言将被忽略。至于“干净” - 代码看起来最好的是个人喜好,但我怀疑很多人会认为它比其旁边的评论更可读。 – 2015-09-14 00:19:38

+0

但是,如果我们发表评论,断言失败后将不会在控制台上打印。 – 2015-09-14 12:08:53

+0

是的,的确如此,但是 - 正如其他人所指出的那样 - 如果您断言失败,那么您首先要做的第一件事就是访问违规代码行。大多数情况下,除非您查看断言失败的上下文,否则您甚至不会知道“a”和“b”的含义,因此无论如何您必须访问代码。如果断言在没有代码见解的情况下应该是可以理解的,那么对于我来说,这将暗示您在这种情况下使用了错误的错误报告机制。 – 2015-09-15 00:14:16

9

这里是我的版本断言宏,它接受的消息,并以明确的方式打印的所有问题:

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

尼斯和清洁,随时在您的代码中使用它=)

+0

不错的一个。非常有用 – Killrazor 2016-06-03 11:55:21

+0

我有点困惑。 #Expr是否被视为直接替换的字符串? #Expr和Expr有什么区别? – 2016-09-22 17:25:30

+0

@MinhTran让我们假设你的断言条件是'x == y'。然后Expr将展开为'if(!(x == y))',这是检查条件的地方,并且#Expr将展开为字符串文字'“x == y”',然后我们将其输入到错误消息中。 – 2016-10-14 07:27:57

相关问题