Как получить среднее из нескольких chrono:: time_points

Формула для получения среднего числа чисел, конечно, хорошо известна:

И эту формулу можно легко использовать для получения среднего значения chrono::duration s:

template <class Rep0, class Period0>
auto
sum(const std::chrono::duration<Rep0, Period0>& d0)
{
    return d0;
}

template <class Rep0, class Period0, class ...Rep, class ...Period>
auto
sum(const std::chrono::duration<Rep0, Period0>& d0,
    const std::chrono::duration<Rep, Period>& ...d)
{
    return d0 + sum(d...);
}

template <class ...Rep, class ...Period>
auto
avg(const std::chrono::duration<Rep, Period>& ...d)
{
    return sum(d...) / sizeof...(d);
}

Но chrono::time_point нельзя добавить друг к другу. Как я могу усреднить time_point s?

Ответ 1

Это помогает начать с предположения, что вы можете добавить time_point s, а затем манипулировать формулой, чтобы устранить эти дополнения:

Сначала выделите t 1 из суммы:

Затем добавьте и вычтите t 1:

Фактор и порядок:

И тогда, поскольку вы вычитаете t 1 столько же раз, сколько вы суммируете, вы можете включить это в сумму:

Теперь вы суммируете duration вместо time_point s! Поскольку у нас уже есть функция для суммирования duration s, усреднение time_point можно легко опираться на это:

template <class Clock, class Duration0, class ...Duration>
auto
avg(const std::chrono::time_point<Clock, Duration0>& t0,
    const std::chrono::time_point<Clock, Duration>& ...t)
{
    return t0 + sum((t - t0)...) / (1 + sizeof...(t));
}

Усреднение одного time_point является особым случаем, поскольку sum duration не обрабатывает суммирование нуля duration (какими будут единицы?). Таким образом, перегрузка для этого случая легко добавляется:

template <class Clock, class Duration0>
auto
avg(const std::chrono::time_point<Clock, Duration0>& t0)
{
    return t0;
}

Это написано на С++ 14. Его можно закодировать в С++ 11, используя синтаксис типа возвращаемого типа, который является более подробным, но вполне выполнимым.