【问题标题】:Absolute value of a std::chrono::duration objectstd::chrono::duration 对象的绝对值
【发布时间】:2014-01-23 23:25:15
【问题描述】:

鉴于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::abschrono 模板的任何特化,在std::chrono::duration 中也看不到任何合适的成员函数。

我应该如何将std::chrono::duration 转换为它的绝对值?

【问题讨论】:

  • 我很好奇。在什么情况下会有用?
  • 不完美但是:auto diff = then &lt; now ? now - then : then - now;
  • @user2079303 任何需要知道两个时间点 (time_point) 之间经过的时间 (duration) 但不关心哪个先发生的情况。
  • 我正在努力为abs(duration) 实用程序提供不止一种用途,这可能就是它不标准的原因。我认为您将不得不将std::abs 应用于持续时间的计数。
  • 我不确定您所说的不止一种用途是什么意思。 std::abs 应用于 int 时只有一种用途......它会删除标志。与duration 相同。由于duration 提供了所有相关的算术运算符,因此当std::abs 具有如此明确的用例时,省略它并没有什么意义。毕竟,我们有 std::abs 用于 std::complexstd::valarray

标签: c++ c++11 chrono


【解决方案1】:

我会这样做:

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);
}

查看我的&lt;chrono&gt; Utilities 列表,了解我希望是标准的其他&lt;chrono&gt; 实用程序。请随意使用它们,将它们推荐给您的标准机构代表,或自己提出。

更新

当我写以上内容时,我已经离开了我的游戏。我不会删除它,因为它为我自己和其他人提供了一个很好的教训,让我知道如何编写chrono实用程序。

我不喜欢它的地方:

  1. 它通过直接操作Rep 不必要地降低了类型安全性。

  2. 它假定文字 0 可以隐式转换为 Rep,或至少与 Rep 相当。

  3. 没有理由不是constexpr

  4. 我对未签名 Rep 的行为不满意。如果有人说:

    自动 d = abs(t1 - t0);

t1t0 基于无符号持续时间,那么这很可能是代码中的逻辑错误。如果t1 &lt; t0,那么您可能会得到一个不正确的、非常大的持续时间。如果那是您真正想要的,那么您不应该使用abs,而只需编写更简单的代码:

   auto d = t1 - t0;

为了解决这些问题,我将abs 的持续时间改写为:

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;
}
  1. duration 具有一元 -,使用即可。

  2. duration 具有可自定义的 zero 特征,这样就不必假设与来自 Rep0 密切合作。就用它吧。

  3. 使用的所有操作都是constexpr,用constexpr标记abs

  4. 静态函数minzeroconstexpr。使用这些来确定Rep 是否已签名比使用诸如!std::is_unsigned 之类的特征更通用。 IE。 Rep 可能是 BigNum 或 C11 timespec(增加了重载算术运算符)。所以“已签名”的问题由min() &lt; zero() 回答。现在这个版本的abs 将不接受duration&lt;unsigned, milli&gt;(例如)。

【讨论】:

猜你喜欢
  • 2018-09-06
  • 2018-02-03
  • 2016-07-20
  • 1970-01-01
  • 2012-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多