在整数 std::chrono::durations 之间转换
Converting between integer std::chrono::durations
我正在使用 std::chrono 编写标准游戏循环。我需要将一个浮点数传递给我的渲染方法,它代表我进入下一帧的距离。为了计算我使用 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 秒无法精确转换为 steady_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 是在减法过程中隐式发生的。我错过了什么?有更好的方法吗?
澄清一下,这是出错的代码行:
lag -= time_per_update;
test.cpp:27:11: error: no viable overloaded '-='
lag -= time_per_update;
~~~ ^ ~~~~~~~~~~~~~~~
I was under the impression the conversion to common_type happens implicitly during the subtraction.
你是对的,但不完全正确。
二进制减法运算符returns两个参数的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;
如果 lag - delta
的 result
不能隐式转换为 lag
的类型,那么你就有问题了(你的例子就是这种情况)。
将 lag
的类型更改为 common
是正确的解决方法:
common lag = steady_clock::duration::zero();
这是另一种方法。这两者之间的选择是风格上的:
auto lag = steady_clock::duration::zero() + updates{0};
最后,作为个人 nit,我喜欢尽量减少(如果不是消除).count()
的使用,因为这相当于 reinterpret_cast
从 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};
现在您对 render
的调用更加简单:
render(lag / time_per_update);
甚至不再需要 common
和 dcommon
(您可以删除它们)。
我正在使用 std::chrono 编写标准游戏循环。我需要将一个浮点数传递给我的渲染方法,它代表我进入下一帧的距离。为了计算我使用 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 秒无法精确转换为 steady_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 是在减法过程中隐式发生的。我错过了什么?有更好的方法吗?
澄清一下,这是出错的代码行:
lag -= time_per_update;
test.cpp:27:11: error: no viable overloaded '-='
lag -= time_per_update;
~~~ ^ ~~~~~~~~~~~~~~~
I was under the impression the conversion to common_type happens implicitly during the subtraction.
你是对的,但不完全正确。
二进制减法运算符returns两个参数的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;
如果 lag - delta
的 result
不能隐式转换为 lag
的类型,那么你就有问题了(你的例子就是这种情况)。
将 lag
的类型更改为 common
是正确的解决方法:
common lag = steady_clock::duration::zero();
这是另一种方法。这两者之间的选择是风格上的:
auto lag = steady_clock::duration::zero() + updates{0};
最后,作为个人 nit,我喜欢尽量减少(如果不是消除).count()
的使用,因为这相当于 reinterpret_cast
从 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};
现在您对 render
的调用更加简单:
render(lag / time_per_update);
甚至不再需要 common
和 dcommon
(您可以删除它们)。