将消息添加到断言

新手上路,请多包涵

我正在寻找一种将自定义消息添加到断言语句的方法。我发现这个问题 Add custom messages in assert? 但消息在那里是静态的。我想做这样的事情:

 assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));

当断言失败时,我想要正常的输出加上例如“x 是 100”。

原文由 tauran 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 323
2 个回答

你在这里不走运。最好的方法是定义自己的 assert 宏。

基本上,它看起来像这样:

 #ifndef NDEBUG
#   define ASSERT(condition, message) \
    do { \
        if (! (condition)) { \
            std::cerr << "Assertion `" #condition "` failed in " << __FILE__ \
                      << " line " << __LINE__ << ": " << message << std::endl; \
            std::terminate(); \
        } \
    } while (false)
#else
#   define ASSERT(condition, message) do { } while (false)
#endif

仅当未定义无调试宏 NDEBUG 时,这将定义 ASSERT 宏。

然后你会像这样使用它:

 ASSERT((0 < x) && (x < 10), "x was " << x);

这比您的用法简单一些,因为您不需要显式地对 "x was "x 进行字符串化,这是由宏隐式完成的。

原文由 Konrad Rudolph 发布,翻译遵循 CC BY-SA 3.0 许可协议

为了接受 Feng Wang 的回答,在较新版本的 C++ 中,任何内联的东西都会被优化掉。所以你可以在一个头文件中有一个内联函数来完成所有的工作。

 inline constexpr void NOT_USED()
{
}

template <class T, class ...ARGS>
inline constexpr void NOT_USED(T && first, ARGS && ...args)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
    static_cast<void>(first);
#pragma GCC diagnostic pop
    NOT_USED(args...);
}

template<typename ... ARGS>
void SAFE_ASSERT(bool test_result, ARGS &&... args)
{
#ifdef _DEBUG
    if(test_result)
    {
        (std::cerr << ... << args) << std::endl;
        abort();
    }
#else
    NOT_USED(test_result, args...);
#endif
}

一些评论:

  1. 如果 _DEBUG 未定义,则函数为空,因此可以 100% 优化

  2. 如果调用有副作用的函数,非调试代码仍然有效:

     my_assert(c++ < --z, "the #define versions do not behave similarly");

这些副作用在这里清晰可见。然而,如果你调用一个函数,可能真的很难知道函数中是否发生了一些原本没有预料到的事情。

不过,有一些方法可以防止这种副作用的发生( 示例)。但总而言之,在某些情况下,您需要调用一个函数进行测试,它可能会产生副作用,因此不需要在非调试代码中进行优化。

  1. 我使用 abort() 因为我知道可以正确停止调试器, std::terminate() 是在现代系统中做同样事情的 C++ 方式,但如果 std::terminate() 没有为您的调试器工作 abort() 将。

  2. NOT_USED() 是为了避免有关未使用的函数参数的警告(如果您没有该警告,您最终可能会遇到预期的错误)。

  3. 我在 snapdev 中有一个实现:参见 safe_assert.hnot_used.h

原文由 Alexis Wilke 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题