鉴于 std::chrono::duration
可以表示两个时间之间的带符号差值,因此需要此类持续时间的绝对值似乎是一种非常常见的情况。例如,以下代码按预期输出 diff: -5
:
using namespace std;
using namespace std::chrono;
auto now = system_clock::now();
auto then = now - seconds(5);
auto diff = then - now;
cout << "diff: " << duration_cast<seconds>(diff).count() << endl;
如果能做这样的事情就好了:
auto diff = abs(then - now);
但是,我在标准中看不到 std::abs
对 chrono
模板的任何特化,也看不到 中任何适当的成员函数>std::chrono::duration
.
我应该如何将 std::chrono::duration
转换成它的绝对值?
最佳答案
我会这样做:
template <class Rep, class Period>
std::chrono::duration<Rep, Period>
abs(std::chrono::duration<Rep, Period> d)
{
Rep x = d.count();
return std::chrono::duration<Rep, Period>(x >= 0 ? x : -x);
}
查看我的 <chrono>
Utilities 列表,了解我希望成为标准的其他 <chrono>
实用程序。请随意使用它们,将它们推荐给您的标准机构代表,或者您自己提出。
更新
当我写以上内容时,我不在游戏中。我不会删除它,因为它为我自己和其他人提供了一个很好的教训,告诉他们如何不编写 chrono
实用程序。
我不喜欢它的地方:
它通过直接操纵
Rep
不必要地降低类型安全。它假定文字 0 可以隐式转换为
Rep
,或者至少可以与constexpr
进行比较。没有理由不是
Rep
。我对 unsigned
t1
的行为不满意。如果有人说:自动 d = abs(t1 - t0);
而t0
和t1 < t0
是基于unsigned duration的,那么这很可能是代码中的逻辑错误。如果是 abs
,那么您可能会得到一个不正确的、非常长的持续时间。如果那是您真正想要的,那么您不应该使用 abs
,而是编写更简单的代码:
auto d = t1 - t0;
为了解决这些问题,我将持续时间的 duration
重写为:
template <class Rep, class Period,
class = typename std::enable_if
<
std::chrono::duration<Rep, Period>::min() <
std::chrono::duration<Rep, Period>::zero()
>::type
>
constexpr
inline
std::chrono::duration<Rep, Period>
abs(std::chrono::duration<Rep, Period> d)
{
return d >= d.zero() ? d : -d;
}
-
有一元duration
,随便用吧。zero
具有可定制的0
特性,因此您不必假设与Rep
中的constexpr
密切合作。就用它吧。使用的所有操作都是
abs
,用constexpr
标记min
。静态函数
zero
和constexpr
是Rep
。使用这些来确定!std::is_unsigned
是否已签名比使用Rep
等特征更通用。 IE。BigNum
可能是timespec
或 C11min() < zero()
(用重载算术运算符增强)。所以问题“已签名”用abs
回答。现在这个版本的duration<unsigned, milli>
将不接受 ojit_code(例如)。
关于c++ - std::chrono::duration 对象的绝对值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21321445/