首页 > 解决方案 > 为什么`std::chrono::weekday`允许但不保留有效范围之外的值?

问题描述

根据C++ 标准的[time.cal.wd.overview]/1部分:

weekday代表民间历法中的一周中的一天。它通常保存范围0为 to的值6,对应于周日到周六,但它可能保存此范围之外的非负值。

同时算术运算执行模7算术强制范围内的结果[0, 6],例如

weekday wd(7);
// wd.ok() == false - wd is invalid
++wd; // wd == weekday(1)
// wd.ok() == true  - wd silently becomes valid

为什么weekday会有这种特殊的行为,特别是为什么[0, 6]算术运算不允许但不保留的值?

标签: c++chronoc++20

解决方案


weekday(unsigned wd)构造函数承诺保存 [0, 255] 范围内的任何值。这样做的理由是:

  1. 它非常快。
  2. 它允许客户端将“未使用”值分配给客户端逻辑中有用的东西。

对于 (2) 的示例:

constexpr weekday not_a_weekday{255};
...
weekday wd = not_a_weekday;
in >> wd;
if (wd == not_a_weekday)
    throw "oops";

weekday算术强制范围回到 [0, 6] 因为如果您编写算法来执行模 7 算术,根本没有范围检查,这就是自然发生的事情。即这是最快的事情。


总而言之:性能是当前weekday规范的基本原理,结合sizeof尽可能小(这也有助于提高性能)。

然而,在尽可能多的性能下,剩下的任何行为(自然发生)都可能有利于标准化并让客户利用这些行为,而不是说它们是 Undefined Behavior TM

事实上,规范尽可能地避免了 UB,而是选择了未指定的行为。例如weekday{300}可能不会存储您想要的值,但它不能重新格式化您的磁盘,并且不允许优化器假装代码不存在。


推荐阅读