我正在寻找一种将自定义消息添加到断言语句的方法。我发现这个问题 Add custom messages in assert? 但消息在那里是静态的。我想做这样的事情:
assert((0 < x) && (x < 10), std::string("x was ") + myToString(x));
当断言失败时,我想要正常的输出加上例如“x 是 100”。
原文由 tauran 发布,翻译遵循 CC BY-SA 4.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
}
一些评论:
如果 _DEBUG
未定义,则函数为空,因此可以 100% 优化
如果调用有副作用的函数,非调试代码仍然有效:
my_assert(c++ < --z, "the #define versions do not behave similarly");
这些副作用在这里清晰可见。然而,如果你调用一个函数,可能真的很难知道函数中是否发生了一些原本没有预料到的事情。
不过,有一些方法可以防止这种副作用的发生( 示例)。但总而言之,在某些情况下,您需要调用一个函数进行测试,它可能会产生副作用,因此不需要在非调试代码中进行优化。
我使用 abort()
因为我知道可以正确停止调试器, std::terminate()
是在现代系统中做同样事情的 C++ 方式,但如果 std::terminate()
没有为您的调试器工作 abort()
将。
NOT_USED()
是为了避免有关未使用的函数参数的警告(如果您没有该警告,您最终可能会遇到预期的错误)。
我在 snapdev 中有一个实现:参见 safe_assert.h
和 not_used.h
。
原文由 Alexis Wilke 发布,翻译遵循 CC BY-SA 4.0 许可协议
3 回答2k 阅读✓ 已解决
2 回答3.9k 阅读✓ 已解决
2 回答3.2k 阅读✓ 已解决
1 回答3.2k 阅读✓ 已解决
1 回答2.7k 阅读✓ 已解决
3 回答3.4k 阅读
1 回答1.6k 阅读✓ 已解决
你在这里不走运。最好的方法是定义自己的
assert
宏。基本上,它看起来像这样:
仅当未定义无调试宏
NDEBUG
时,这将定义ASSERT
宏。然后你会像这样使用它:
这比您的用法简单一些,因为您不需要显式地对
"x was "
和x
进行字符串化,这是由宏隐式完成的。