C++|如何使用C++20解决一系列运行时的错误( 二 )


救世主来了:C++20C++20 为我们引入了一个重要的工具来启用编译时检查 , 即consteval 。consteval属于 constexpr家族 , 但该语言保证用consteval修饰的函数可以在编译时得到评估 。 一个名为fmtlib 的著名库引入了编译时检查作为核心API的一部分 , 并且它在不更改任何调用点的情况下这样做 , 假设调用点根据库的格式正确 。 想象一下fmt的简化版本 , 如下图所示:

意图是格式应始终等于”有效” , 而T应始终为int 。在这种情况下 , 根据库 , main中的代码格式不正确 , 但在编译时没有任何验证 。fmtlib使用用户定义类型的一个小技巧完成了编译时检查:

注意:你需要使用std::type_identity_t技巧来防止检查参与类型推导 。我们只希望它推断出其余的参数并将其推断的类型用作Checker的模板参数 。
将以上技术汇总起来上面的代码很强大 , 因为它为我们提供了一个工具 , 可以在不更改任何格式良好的调用者的情况下执行额外的安全检查 。 使用上述技术 , 我们将编译时检查应用于所有错误、警告和消息处理例程 。 编译器中使用的代码几乎与上面的fmt相同 , 只是Checker的参数是一个ErrorNumber 。
我们总共确定了大约120个实例 , 其中我们将错误数量的参数传递给诊断API , 或者我们为特定格式说明符传递了错误的类型 。 多年来 , 我们收到了关于在发出诊断或直接ICE(内部编译器错误)时奇怪的编译器行为的错误 , 因为格式说明符正在寻找不正确或不存在的参数 。 使用C++20 , 我们在很大程度上消除了未来发生此类错误的可能性 , 同时为我们提供了安全重构诊断消息的能力 , 这可以通过一个小关键字实现:consteval 。
总结宇宙的尽头是 , C++模板 。