在整数std :: chrono :: durations

时间:2019-06-02 07:42:53

标签: c++ std chrono

我正在使用std :: chrono编写标准的游戏循环。我需要将float传递给我的render方法,该方法代表到下一帧的距离。要使用chrono :: duration的count()方法计算数字,因此我需要将两个持续时间转换为相同的比率。

void engine::run() {
  using namespace std::chrono;
  using updates = duration<steady_clock::rep, std::ratio<1, 40>>;
  using common = std::common_type<updates, steady_clock::duration>::type;

  constexpr updates time_per_update{1};
  auto previous = steady_clock::now();
  auto lag = steady_clock::duration::zero();

  while (!quit) {
    auto now = steady_clock::now();
    auto delta = now - previous;

    previous = now;
    lag += delta;

    while (lag >= time_per_update) {
      lag -= time_per_update;
      update(time_per_update);
    }

    render(common{lag}.count() / static_cast<double>(common{time_per_update}.count()));
  }
}

如果我将'updates'中的比率更改为41,则在减法时会出现编译错误,因为1/41秒的时间无法精确转换为stable_clock :: duration。但是,当我将代码重写为此时,它可以正常编译:

void engine::run() {
  using namespace std::chrono;
  using updates = duration<steady_clock::rep, std::ratio<1, 41>>;
  using common = std::common_type<updates, steady_clock::duration>::type;

  constexpr common time_per_update{updates{1}};
  auto previous = steady_clock::now();
  common lag = steady_clock::duration::zero();

  while (!quit) {
    auto now = steady_clock::now();
    auto delta = now - previous;

    previous = now;
    lag += delta;

    while (lag >= time_per_update) {
      lag -= time_per_update;
      update(time_per_update);
    }

    render(lag.count() / static_cast<double>(time_per_update.count()));
  }
}

我的印象是,在减法期间隐式发生了向common_type的转换。我想念什么?有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

为澄清起见,这是发生错误的代码行:

 lag -= time_per_update;

test.cpp:27:11: error: no viable overloaded '-='
      lag -= time_per_update;
      ~~~ ^  ~~~~~~~~~~~~~~~
  

我的印象是,在减法期间隐式发生了向common_type的转换。

您是正确的,但不完全正确。

binary 减法运算符返回两个参数的common_type

template <class Rep1, class Period1, class Rep2, class Period2>
  constexpr
  typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2>>::type
  operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);

但是-=运算符必须等效于:

lag = lag - delta;

如果result的{​​{1}}不能隐式转换为lag - delta的类型,那么您就遇到了问题(例如您的示例)。

lag的类型更改为lag是正确的解决方法:

common

这是另一种方法。两者之间的选择在风格上是

common lag = steady_clock::duration::zero();

最后,就像个人一样,我想尽量减少(如果不能消除)对auto lag = steady_clock::duration::zero() + updates{0}; 的使用,因为这相当于.count()reinterpret_cast到{{1} }(或标量)。在您的示例中,这并不难做到,并且不会降低效率。

首先添加与duration等效的内容,并使用integral作为表示形式:

common

然后,您只需将double转换为using dcommon = duration<double, common::period>; 并将其除以lag即可得到比率:

dcommon

最后,您还可以考虑另一种样式上的变化:首先将time_per_update表示为基于render(dcommon{lag} / time_per_update); 的前端:

lag

现在,您对double的呼叫更加简单:

auto lag = steady_clock::duration::zero() + updates{0} + duration<double>{0};

甚至不再需要renderrender(lag / time_per_update); (您可以删除它们)。