在我的程序中,我想使用显示错误消息的断言。除了众所周知的C和C ++解决方案之外,BOOST提供的“真实”解决方案BOOST_ASSERT_MSG( expr, msg )
(另见assert() with message)
但是静态信息对我来说还不够,我还想有时显示失败的变量,例如:在类似
的情况下BOOST_ASSERT_MSG( length >= 0, "No positive length found! It is " << length )
正如您所看到的,我想将消息“字符串”格式化为stringstream
或ostream
,因为这样我可以轻松地显示自定义类型(假设我已定义了相关内容)格式化功能)。
此处的问题是BOOST_ASSERT_MSG
默认需要char const *
,因此不兼容。
有没有办法以这样的方式重新定义/重载assertion_failed_msg()
,使用流作为消息将起作用?怎么样?
(我的天真方法失败了,因为编译器首先要对消息本身做operator<<("foo",bar)
...)
答案 0 :(得分:6)
您可以定义自己的宏
#define ASSERT_WITH_MSG(cond, msg) do \
{ if (!(cond)) { std::ostringstream str; str << msg; std::cerr << str.str(); std::abort(); } \
} while(0)
答案 1 :(得分:5)
实现这一目标相对微不足道。
BOOST_ASSERT_MSG( length >= 0, (std::stringstream() << "No positive length found! It is " << length).str().c_str() )
答案 2 :(得分:1)
我使用BOOST_ASSERT_MSG
和我自己的包装器,因此指定多个operator<<
的断言消息似乎不太复杂。
#if defined ASSERT_ENABLED
#define ASSERT(cond, msg) {\
if(!(cond))\
{\
std::stringstream str;\
str << msg;\
BOOST_ASSERT_MSG(cond, str.str().c_str());\
}\
}
#else
#define ASSERT(...)
#endif
用法示例,提供您输出到cout
的自定义消息:
ASSERT(execSize == (_oldSize - remaining), "execSize : " << execSize << ", _oldSize : " << _oldSize << ", remaining : " << remaining);
它的作用是,如果定义了ASSERT_ENABLED
,则启用断言消息。 if(!(cond))
部分是优化,如果msg
为cond
true
指定的代价高昂的字符串操作
答案 3 :(得分:0)
这是不依赖宏的解决方案。相反,它使用了一点模板和lambda语法。
template<typename Fn>
void assert_fn( bool expr, Fn fn) {
if (!expr) {
fn();
abort();
}
}
自变量fn
可以是任何可调用的。
例如,您可以这样称呼它:
assert_fn( a==b, [&](){ cout << "Assertion failed: a="<< a <<
" is different from but b=" << b << endl; } );
优点是输出不会显式调用中止,并且输出是完全可定制的。当然,此优势是lambda函数样板的七个额外字符:[&](){}
)
答案 4 :(得分:0)
如果仅在Windows上工作,则可以查看assert
宏。引擎盖下使用_wassert
。您可以使用它编写自己的assert宏。例如,在我的情况下,如果我想表达一点,我想显示没有条件的断言:
#ifdef DEBUG
const std::wstring assert_msg = /* build the string here */;
_wassert(assert_msg.c_str(), _CRT_WIDE(__FILE__), (unsigned)(__LINE__));
#endif
我认为在其他操作系统上,您可以执行相同的操作,只需查看assert
宏即可。