我正在阅读使用滑稽持续时间单位microfortnights
的{{3}}来以令人难忘的方式说明一个好点。
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>>;
但是这些将是两种不同的类型,而不是相同的类型。第一个表达式更容易检查是否正确。但是这个部分有许多表示,第二部分可以说是规范的,因而是首选的。如果我有太多类型在我的程序中游荡,实际上代表同一个单元,那么这可能会导致不必要的模板代码膨胀。
答案 0 :(得分:29)
为了简洁起见,我忽略了命名空间。 duration
位于名称空间std::chrono
中,ratio
位于名称空间std
中。
有两种不错的方法可以始终确保将ratio
缩减为最低项,而无需自行进行算术运算。第一个是非常直接的:
直接制定
如果您只想直接跳到microfortnights
,但无需弄清楚减少的分数86,400 * 14 / 1,000,000是756/625,只需在{{1}之后添加::type
}}:
ratio
每个using microfortnights = duration<long, ratio<86400*14, 1000000>::type>;
的嵌套type
是另一个ratio<N, D>
,其中ratio<Nr, Dr>
是缩减的分数Nr/Dr
。如果N/D
已减少,则N/D
与ratio<N, D>::type
的类型相同。事实上,如果我已经发现756/625是正确的减少分数,但只是偏执地认为可能会进一步减少,我本可以写:
ratio<N, D>
因此,如果您怀疑using microfortnights = duration<long, ratio<756, 625>::type>;
是以最低级别表达,或者只是不想被检查困扰,您可以随时将ratio
附加到::type
1}}输入只是为了确定。
详细的表述
自定义持续时间单位通常会作为家庭的一部分弹出。将整个系列用于代码通常很方便。例如,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
using days = duration<long, ratio<86400>>;
是一个 typedef-name ,乘法的结果已经减少到最低值。所以上面的是完全相同的类型 as:
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>>;
您甚至可以在同一个翻译单元中使用这两个定义,并且不会出现重新定义错误。无论如何,您现在可以说:
microfortnights
我们最终得到std::micro
的 typedef-name 与我们直接制定的完全相同的类型,但通过一系列更简单的转换。我们仍然不必为将分数减少到最低项而烦恼,我们现在有几个有用的单位而不是一个。
另请注意使用std::ratio<1, 1000000>
代替{{1}}。这是另一个避免粗心错误的地方。很容易(至少对我来说)错误输入(和误读)零的数量。