形成自定义std :: chrono :: durations和std :: ratios的最佳方法是什么?

时间:2015-01-10 19:36:56

标签: c++ c++11 chrono

我正在阅读使用滑稽持续时间单位microfortnights的{​​{3}}来以令人难忘的方式说明一个好点。

typedef std::ratio<756, 625> microfortnights;
std::chrono::duration<int, microfortnights> two_weeks(1000000);

问题出现在我身上:

  

如果我真的想这样做(更可能是其他一些非平凡的事情   持续时间,例如帧中可用的时间,或N个周期   处理器),最好的方法是什么?

我知道ratio<N, D>会创建与ND的每个值相关联的唯一类型。因此,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>>;

但是这些将是两种不同的类型,而不是相同的类型。第一个表达式更容易检查是否正确。但是这个部分有许多表示,第二部分可以说是规范的,因而是首选的。如果我有太多类型在我的程序中游荡,实际上代表同一个单元,那么这可能会导致不必要的模板代码膨胀。

1 个答案:

答案 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/Dratio<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}}。这是另一个避免粗心错误的地方。很容易(至少对我来说)错误输入(和误读)零的数量。