我正在尝试为自己的项目编写自己的自定义断言。该项目将使用 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/