编译期的异常检测
表达式(expression)在编译期检测得到的结果是一个常数,这意味着可以利用编译期(而非代码)来作检测。
我们可以传给编译期一个语言构造(lauguage construct),如果是非零表达式则合法,零表达式则非法。当传入一个表达式而其值为零时,编译期会发出一个编译期的错我信息;
最简单的方式称为“compil-time-assertions”。它依赖一个事实:大小为零的array是非法的。
#define STATIC_CHECK(expr) { char unnamed[(expr) ? 1 : 0];}
这种方法能够产生错误,但不能表达正确信息。即产生的告警不能正确的表达错误信息。
一个较好的方法是依赖一个名称带有意义的template(因为编译期会在错误信息中指出template的名称):
template<bool> struct ComplileTimeError; template<> struct ComplileTimeError<true> {}; #define STATIC_CHECK(expr) \ (ComplileTimeError<(expr)> != 0>())
ComplileTimeError需要一个非class的参数(一个bool参数),而且它只针对true有定义。
如果尝试实现ComplileTimeError<false>, 编译器会发出“undefined specialization ComplileTimeError<false>”。
这个解决了我们从无法识别的错误到我定制的错误消息,但我们可以继续改进,定制我我们的错误消息:
// 编译期 的 静态检验 template<bool> struct CompileTimeChecker { CompileTimeChecker(...); }; template<> struct CompileTimeChecker<false> {}; #define STATIC_CHECK(expr, msg) { \ class ERROR_##msg{}; \ (void)sizeof(CompileTimeChecker<expr>(ERROR_##msg{})); \ } template<class To, class From> To safe_reinterpret_cast(From from) { STATIC_CHECK(sizeof(From) <= sizeof(To), Destination_Type_Too_Narrow); return reinterpret_cast<To>(from); }
这样如果我们有错误,编译器会产生 无法从“safe_reinterpret_cast::ERROR_Destination_Type_Too_Narrow”转换为“CompileTimeChecker<false>”, 这样我们就可以通过编译告警知道错误的信息了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现