Поскольку мы определяли продолжительность промежутка времени между двумя абсолютными точками во времени (они хранятся в переменных tic
toc
), нам не нужно знать, были ли эти точки искажены глобально. Даже если часы спешат или опаздывают на 112 лет 5 часов 10 минут и 1 секунду (или другое значение), это не отражается на tic
, и до того, как сохраняем временную точку toc
, для часов нельзя выполнить микронастройку (что случается время от времени во многих системах), поскольку это исказит измерение. Согласно данным требованиям, оптимальным выбором является steady_clock
. Их реализация может быть основана на счетчике временных меток процессора, который всегда монотонно увеличивается с момента запуска системы.О’кей, теперь, когда мы выбрали правильный объект time
chrono::steady_clock::now()
. Функция now
возвращает значение типа chrono::time_point
. Разность между двумя такими значениями (toc–tic
) является chrono::duration
.Поскольку данный тип является основным для текущего раздела, все немного усложняется. Рассмотрим интерфейс шаблонного типа duration
template<
class Rep,
class Period = std::ratio<1>
> class duration;
Можно изменить значения параметров Rep
Period
. Значение параметра Rep объяснить легко: это всего лишь численный тип переменной, который используется для сохранения значения времени. Для существующих в STL единиц измерения времени таковым обычно выступает тип long long int
. В данном примере мы выбрали тип double
и благодаря этому можем сохранять по умолчанию значения в секундах, а затем преобразовывать их в милли- или микросекунды. Если у нас есть промежуток времени, равный 1.2345
секунды и имеющий тип chrono::seconds
, то значение будет округлено до одной целой секунды. Таким образом, нужно сохранить разность между переменными tic
и toc
в переменной типа chrono::microseconds
, а затем преобразовать его в менее точные единицы. Из-за выбора типа double
для Rep
можно выполнять преобразование к более и менее точным единицам и терять минимальный объем точности, что не влияет на наш пример.Мы использовали Rep = double
Period
:using seconds = chrono::duration
using milliseconds = chrono::duration
ratio_multiply
using microseconds = chrono::duration
ratio_multiply
Секунды — самая простая в описании единица времени, поскольку можно воспользоваться конструкцией Period = ratio<1>
seconds::period
(который представляет собой всего лишь функцию-геттер для параметра Period
) на milli
— псевдоним типа std::ratio<1, 1000>
(std::ratio
— это дробное значение a/b
). Тип ratio_multiply
, по сути, является ratio
на другой.Это может показаться непонятным, так что рассмотрим пример: команда ratio_multiply
ratio<8, 15>
, поскольку (2/3) * (4/5) = 8/15
.Полученные описания типов эквивалентны следующим описаниям:
using seconds = chrono::duration
using milliseconds = chrono::duration
using microseconds = chrono::duration
После получения этих типов можно легко выполнять преобразования между ними. При наличии промежутка времени d
seconds
можно преобразовать его в тип milliseconds
, передав в конструктор другого типа — milliseconds(d)
.Дополнительная информация