文章图片
文章图片
文章图片
C++20已经发布了一阵子了 , 并已经被MSVC v16.11及以上版本所支持 。 今天的文章的主题 , 不是讲如何使用它 , 而是讲我们作为编译器开发人员 , 是如何借助C++20来有效地清除一些列运行时错误 。 不多啰嗦 , 直接上东西 。
最初的做法在设计编译器时 , 你需要考虑的第一件事就是需要提醒开发者他的代码是否有错误或者潜在的非预期行为 。 在MSVC编译器的实现中 , 我们采用了如下图所示的错误模型:
上图中的error函数确实能正常工作 , 因为每个错误代码(ErrorNumber)都有一个对应的错误字符串 , 用来提示给开发人员 , 字符串的对应关系千差万别 , 可以是简单的如 C2056 -> “illegal expression” , 到复杂的如 C7627 -> “‘%1$T’: is not a valid template argument for ‘%2$S'” , 但是细心的朋友可能注意到了 , 错误字符串里的%1$T和%2$S代表什么意思呢?
这些是一些编译器特有的格式说明符 , 用来向开发者显示比较容易理解的一些特定的结构体类型 。
格式说明符是一把双刃剑我们作为编译器开发者 , 格式说明符确实提供了很大的灵活性和功能 。 格式说明符可以更清楚地说明错误触发的原因 , 并为用户提供有关问题的更多上下文信息 。 格式说明符的问题在于它们在调用上文中提到的error函数时没有进行类型检查 , 所以如果我们碰巧参数类型错误或根本没有传递参数 , 它几乎肯定会在稍后出现运行时错误 。当你想要将错误信息字符串重构为更清晰的内容时也会出现其他问题 , 但要做到这一点 , 你需要查询该错误消息的每个调用者 , 并确保这项重构与传递给错误的实际参数保持一致 。
在设计一个可以对格式说明符进行检查的系统时 , 我们有三个高层目标:
1. 验证在编译时传递到我们的诊断API的参数类型 , 以便尽早地发现错误 。
2. 尽量减少对诊断API调用者所做的更改 。 这是为了确保格式良好的调用保留其原始结构(也不会中断未来的调用) 。
3. 最小化对被调用者的实现细节所做的更改 。 我们不应该在运行时改变诊断程序的行为 。
当然 , 后来的C++标准引入了一些解决方案 , 可以帮助解决这个问题 。 一方面 , 一旦将可变参数模板引入语言中 , 我们可以尝试一些模板元编程来尝试对错误调用进行类型检查 , 但这需要单独地查找表 , 因为constexpr和模板的功能有限 。 C++14/17都对constexpr和非类型模板参数进行了很多改进 。 类似下图中的一种做法就比较有用:
【C++|如何使用C++20解决一系列运行时的错误】因此 , 我们最终找到了一个工具用来在编译期检查格式说明符的正确性 。 但是还有一个问题没有解决:我们仍然没有办法静默地检查所有现有的错误调用 , 这意味着我们必须在错误调用点之间添加一个额外的间接层 , 以确保ErrorNumber可以在编译时获取字符串并检查对应的参数类型 。
在C++17中 , 下面的代码不会正常工作:
我们不能让error函数本身成为constexpr , 因为它做了很多对constexpr不友好的事情 。此外 , 将所有调用站点调整为以下内容:error(a b c) 以便我们可以将错误号作为编译时表达式进行检查 , 这是令人讨厌的 , 并且会在编译器中导致大量不必要的折腾 。
救世主来了:C++20C++20 为我们引入了一个重要的工具来启用编译时检查 , 即consteval 。consteval属于 constexpr家族 , 但该语言保证用consteval修饰的函数可以在编译时得到评估 。 一个名为fmtlib 的著名库引入了编译时检查作为核心API的一部分 , 并且它在不更改任何调用点的情况下这样做 , 假设调用点根据库的格式正确 。 想象一下fmt的简化版本 , 如下图所示:
意图是格式应始终等于”有效” , 而T应始终为int 。在这种情况下 , 根据库 , main中的代码格式不正确 , 但在编译时没有任何验证 。fmtlib使用用户定义类型的一个小技巧完成了编译时检查:
注意:你需要使用std::type_identity_t技巧来防止检查参与类型推导 。我们只希望它推断出其余的参数并将其推断的类型用作Checker的模板参数 。
- 宁德|如何提升引力魔方的转化率
- 小米科技|2022年初,小米笔记本该如何选择?这些性价比很高
- 闪存|日本的智能机使用情况,是苹果多还是安卓多,哪个牌子最受欢迎?
- |装宽带师傅:拒绝使用用户自己买的七类网线
- 显卡|华为系列手机体验如何,只有用过的人才知道,你觉得呢?
- 蓝牙耳机|蓝牙耳机玩腻了,试试静电耳机,看看百元价位如何演绎半千品质
- 编程|拔掉SIM卡,关机,使用非智能手机,行程码就不知道你的行踪了?
- Win10|Win10家庭版如何启用使用本地组策略
- 零售业|美国选择孤注一掷:2400亿美元投向科技产业,我们应该如何应对
- 飞利浦|如何在 MacOS 和 Windows 上捕捉窗口