【问题标题】:c++11 chrono conditional statementsc++11 chrono 条件语句
【发布时间】:2016-03-04 19:32:18
【问题描述】:

有人能描述一下下面的代码吗?

template<typename _Rep2, typename = typename
       enable_if<is_convertible<_Rep2, rep>::value
         && (treat_as_floating_point<rep>::value
             || !treat_as_floating_point<_Rep2>::value)>::type>
  constexpr explicit duration(const _Rep2& __rep)
  : __r(static_cast<rep>(__rep)) { }

template<typename _Rep2, typename _Period2, typename = typename
       enable_if<treat_as_floating_point<rep>::value
         || (ratio_divide<_Period2, period>::den == 1
             && !treat_as_floating_point<_Rep2>::value)>::type>
  constexpr duration(const duration<_Rep2, _Period2>& __d)
  : __r(duration_cast<duration>(__d).count()) { }

【问题讨论】:

  • 我们不知道你想从这个问题中得到什么。代码有问题吗?
  • 究竟想要我们解释一下这段代码是什么?没有人有时间对此进行全面分析。

标签: c++11 chrono


【解决方案1】:

这些是std::chrono::duration 构造函数的 gcc/libstdc++ 实现。我们可以一次看一个:

template <typename _Rep2,
          typename = typename enable_if
          <
              is_convertible<_Rep2, rep>::value &&
              (treat_as_floating_point<rep>::value ||
              !treat_as_floating_point<_Rep2>::value)
          >::type>
constexpr
explicit
duration(const _Rep2& __rep)
    : __r(static_cast<rep>(__rep))
    { }

格式化有助于提高可读性。风格是什么并不重要,只要它有一些。 ;-)

第一个构造函数是constexprexplicit,这意味着如果输入是编译时常量,则构造的持续时间可以是编译时常量,并且输入不会隐式转换为持续时间。

此构造函数的总体目的是显式将标量(或标量的仿真)转换为chrono::duration

模板参数列表中的第二个typename 是对_Rep2 的约束。它说:

  1. _Rep2 必须隐式转换为reprepduration 的表示类型),并且

  2. 要么rep 是浮点类型(或模拟浮点类型),要么_Rep2 不是浮点类型(或模拟浮点类型)。

如果不满足这些约束,则此构造函数实际上不存在。这些约束的效果是您可以从浮点和整数参数构造基于浮点的durations,但基于整数的durations 必须从整数参数构造。

此约束的基本原理是防止静默丢弃浮点参数的小数部分。例如:

minutes m{1.5};  // compile-time error

这个不会编译,因为minutes 是基于整数的,并且参数是浮点数,如果它编译了,它会默默地丢弃.5 导致1min

现在是第二个chrono::duration 构造函数:

template <typename _Rep2,
          typename _Period2,
          typename = typename enable_if
          <
              treat_as_floating_point<rep>::value ||
              (ratio_divide<_Period2, period>::den == 1 &&
              !treat_as_floating_point<_Rep2>::value)
          >::type>
constexpr
duration(const duration<_Rep2, _Period2>& __d)
    : __r(duration_cast<duration>(__d).count())
    { }

此构造函数用作 converting chrono::duration 构造函数。也就是说,它将一个单位转换为另一个单位(例如,hoursminutes)。

同样,模板参数Rep2Period2 有一个约束。如果不满足这些约束,则构造函数不存在。约束是:

  1. rep 是浮点数,或者

  2. _Period2 / period 产生分母为 1 的 ratio_Rep2 是整数类型(或其仿真)。

此约束的效果是,如果您有浮点持续时间,那么 任何 其他持续时间(整数或基于浮点的)将隐式转换为它。

但是,基于整数的持续时间更加挑剔。如果您要转换为基于整数的持续时间,则源持续时间不能是基于浮点的并且从基于整数的源持续时间到目标的转换基于整数的持续时间必须准确。也就是说,转换不能除以除 1 之外的任何数字(只能相乘)。

例如:

hours h = 30min;  // will not compile
minutes m = 1h;   // ok

第一个示例无法编译,因为它需要除以 60,导致 h 不等于 30min。但是第二个示例可以编译,因为m 将完全等于1h(它将保持60min)。

你可以从中得到什么:

  1. 始终&lt;chrono&gt; 为您进行转换。如果您在代码中乘以或除以 60 或 1000(或其他),则不必要地引入了错误的可能性。此外,如果您将所有转换委托给&lt;chrono&gt;&lt;chrono&gt; 会通知您是否有任何有损转换。

  2. 尽可能使用隐式&lt;chrono&gt; 转换。它们要么编译并准确,要么不编译。如果它们不编译,则意味着您要求进行涉及截断错误的转换。可以要求截断错误,只要您不意外这样做。请求截断转换的语法是:

    hours h = duration_cast<hours>(30min);  // ok, h == 0h
    

【讨论】:

  • 非常感谢。很好的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-21
  • 2011-07-18
  • 1970-01-01
  • 2016-05-31
  • 2020-09-13
相关资源
最近更新 更多