C++ 自定义断言

标签 c++ c++11 expression assert

我正在尝试为自己的项目编写自己的自定义断言。该项目将使用 c++11 编写。

断言必须具有以下品质:

它必须作为表达式保存并且可以赋值。 例如。我应该能够编写这样的代码 int x = custom_assert(1/y);

它必须被重载以接受带有消息和没有消息的断言。 例如 int x = custom_assert(1/y, "Error divide by zero"); 这段代码和上面的代码都是可编译和可接受的。

在 Release模式下必须没有副作用 例如。 int x = custom_assert(1/y); 在 Release模式下将变为 int x = 1/y;

最重要的是,它必须在做出断言的特定点中断。它将使用 __debugbreak() 作为其评估表达式的一部分。

以下是我的尝试:

#include <string>

bool DoLog(std::string msg, std::string file, int line); //Prints to std::cerr and returns HALT macro


#if defined(_DEBUG) || defined(DEBUG)
#define HALT true
#define NT_ASSERT_BASE(x, msg) (!(x) && DoLog((msg), __FILE__, __LINE__) && (__debugbreak(),1))
#else
#define HALT false
#define NT_ASSERT_BASE(x,msg) (x)
#endif//debug/release defines

//--- Can't implement these until I can return the expression ---
//#define GET_MACRO(_1,_2,_3,NAME,...) NAME
//#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2)(__VA_ARGS__)

#define NT_ASSERT(expression, msg) NT_ASSERT_BASE(expression,msg)

如您所见,我的自定义断言在两个方面失败了,即被保留为表达式和可赋值,以及重载(我无法实现,直到我弄清楚如何将其保留为表达式。

总而言之,我可能是在追星,这个宏实际上可能是做不出来的。 (我希望不是这样)

非常感谢。

最佳答案

据我所知,这无法在标准 C++ 中完成

无法将 __debugbreak() 放入扩展代码中,同时传递未修改的表达式结果,因为您需要两次结果:一次用于测试它,这会将其隐式转换为 bool,并在最后返回一次。

有两种选择:

  • 使用 gcc 和 clang 的 ({})使用 auto 变量构造以保存结果。这将排除 MSC++,但我想你想要那个,因为 __debugbreak() 是 MSC++ 的错误功能。

  • 放弃要求调用站点上的 __debugbreak(),接受当它停止时必须向上一级并将其作为模板函数。

    • lambda 表达式比模板函数更适合。它会使中断出现在宏站点,但它仍将作为单独的堆栈帧出现在调用堆栈中。它还需要 C++11 支持(它是 5 年前发布的,但某些平台可能没有)。

关于C++ 自定义断言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35018187/

相关文章:

C++ MFC - 代码执行失败而不在 CDialog::OnSize 事件 (GetWindowRect) 上引发运行时错误

c++ - 我可以在同一个进程中使用同一个 DLL 的两个不兼容版本吗?

c++ - 从文件 C++ 中保存和读取双 vector

c++ - 如何从模板参数包中删除类型?

c# - 从 Expression 函数获取父属性

c# - 创建可在运行时计算的表达式

c++ - 无法通过引用捕获 lambda 中的成员变量

c++ - 对象数组如何初始化每个对象的成员变量?

c++ - 覆盖常量表达式?

r - 为 ggplot 图例动态创建表达式?