我正在阅读这个出色的答案,它使用滑稽的持续时间单位microfortnights
以令人难忘的方式说明一个好的观点。
typedef std::ratio<756, 625> microfortnights;
std::chrono::duration<int, microfortnights> two_weeks(1000000);
我想到了一个问题:
如果我真的想这样做(更有可能是其他一些非平凡的 持续时间,例如帧期间或 N 个周期期间的可用时间 处理器),最好的方法是什么?
我知道ratio<N, D>
将创建一个与 N
和 D
的每个值相关联的唯一类型。 所以ratio<4, 6>
与ratio<2, 3>
是不同的类型,即使它们代表相同的(减少的)分数。 我是否总是必须进行数学运算才能将转换系数简化为减少的期限?
写起来会更方便:
using microfortnights = std::chrono::duration<long, ratio<86400*14, 1000000>>;
而不是:
using microfortnights = std::chrono::duration<long, ratio<756, 625>>;
但是,这将是两种不同的类型,而不是相同的类型。 第一个表达式更易于检查正确性。 但是这个分数有很多表示,第二个可以说是规范的,因此是首选。 如果我有太多类型在我的程序中徘徊,这些类型实际上代表同一个单元,那么这可能会导致不必要的模板代码膨胀。
为了简洁起见,我忽略了命名空间。 duration
在命名空间 std::chrono
中,ratio
在命名空间std
中。
有两种好方法可以始终确保您的ratio
减少到最低项,而无需自己进行算术。 第一个非常直接:
直接配方
如果您只想直接跳到 microfortnights
,但不必弄清楚 86,400*14/1,000,000 的简化分数是 756/625,只需在ratio
后添加 ::type
:
using microfortnights = duration<long, ratio<86400*14, 1000000>::type>;
每个ratio<N, D>
的嵌套type
是另一个ratio<Nr, Dr>
其中Nr/Dr
是减少分数N/D
。 如果N/D
已经减少,则ratio<N, D>::type
与ratio<N, D>
的类型相同。 事实上,如果我已经发现 756/625 是正确的减少分数,但只是偏执地认为它可以进一步减少,我本可以写:
using microfortnights = duration<long, ratio<756, 625>::type>;
因此,如果您怀疑您的ratio
是以最低术语表示的,或者只是不想为检查而烦恼,您可以随时将::type
附加到您的ratio
类型中以确保。
冗长的表述
自定义持续时间单位通常作为系列的一部分弹出。 让整个系列可用于您的代码通常很方便。 例如microfortnights
显然与fortnights
有关,而又与weeks
有关,而是从days
派生的,而是从hours
派生的(如果你愿意,也可以从seconds
派生)。
您不仅可以使整个家庭可用,还可以通过最简单的转换将一个家庭成员与另一个家庭成员联系起来来减少出错的机会。 此外,使用 std::ratio_multiply
和 std::ratio_divide
,而不是乘以文字也意味着您不必在任何地方保留插入::type
以确保您将ratio
保持在最低的术语中。
例如:
using days = duration<long, ratio_multiply<hours::period, ratio<24>>>;
ratio_multiply
是乘法结果的 typedef-name 已经减少到最低项。 所以以上是完全相同的类型:
using days = duration<long, ratio<86400>>;
您甚至可以将两个定义放在同一个翻译单元中,并且不会收到重新定义错误。 无论如何,您现在可以说:
using weeks = duration<long, ratio_multiply<days::period, ratio<7>>>;
using fortnights = duration<long, ratio_multiply<weeks::period, ratio<2>>>;
using microfortnights = duration<long, ratio_multiply<fortnights::period, micro>>;
我们最终得到了一个 typedef-name microfortnights
它与我们的直接公式中的类型完全相同,但通过一系列更简单的转换。 我们仍然不必为将分数减少到最低项而烦恼,我们现在有几个有用的单位,而不仅仅是一个。
另请注意使用std::micro
代替std::ratio<1, 1000000>
。 这是避免粗心错误的另一个地方。 很容易(至少对我来说)错误输入(和误读)零的数量。