断言动态消息?

时间:2012-08-12 11:39:18

标签: c++ boost assert

在我的程序中,我想使用显示错误消息的断言。除了众所周知的C和C ++解决方案之外,BOOST提供的“真实”解决方案BOOST_ASSERT_MSG( expr, msg )(另见assert() with message

但是静态信息对我来说还不够,我还想有时显示失败的变量,例如:在类似

的情况下
BOOST_ASSERT_MSG( length >= 0, "No positive length found! It is " << length )

正如您所看到的,我想将消息“字符串”格式化为stringstreamostream,因为这样我可以轻松地显示自定义类型(假设我已定义了相关内容)格式化功能)。

此处的问题是BOOST_ASSERT_MSG默认需要char const *,因此不兼容。

有没有办法以这样的方式重新定义/重载assertion_failed_msg(),使用流作为消息将起作用?怎么样?
(我的天真方法失败了,因为编译器首先要对消息本身做operator<<("foo",bar) ...)

5 个答案:

答案 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))部分是优化,如果msgcond

,则会避免宏参数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宏即可。