Должен ли я использовать типы времени с высоким разрешением в качестве параметров, чтобы избежать duration_cast? - PullRequest
1 голос
/ 28 мая 2020

Я читал, что если тип с самым высоким разрешением, который использует ваша программа, - это, скажем, milliseconds, и этот тип будет охватывать весь диапазон, в котором находятся ваши значения, вам следует в основном придерживаться его, чтобы не иметь duration_casts везде. Вместо этого у вас будет только один внутри функции, если все, что вам нужно, это точность, скажем, seconds.

Однако для типов возвращаемых функций вы бы наоборот вернули наименьшее возможное разрешение, чтобы иметь наименьшее возможное количество duration_cast (а здесь даже оптимальную производительность, поскольку в этом случае вы все равно выполняете преобразование).

К сожалению, я не нашел источника, который освещает эту проблему всесторонне (или действительно, никак). Следует ли таким образом использовать std::chrono (при условии, что кто-то не хочет последнего возможного бита производительности)?

1 Ответ

2 голосов
/ 28 мая 2020

Я не думаю, что в целом можно много сказать об этой стратегии, за исключением того, что да , вы не хотите без нужды засорять свой код duration_cast. Зарезервируйте duration_cast только для тех преобразований, точность которых вы хотите усечь. И в этих случаях следует учитывать, что duration_cast обрезается до нуля. В C ++ 17 представлены 3 другие стратегии усечения:

  • floor: усечение в сторону отрицательной бесконечности
  • ceil: усечение в сторону положительной бесконечности
  • round : усечение в сторону ближайшего, в сторону даже на t ie

(Если вы используете C ++ 11/14, вы можете взять эти удобные утилиты здесь ).

И, конечно, если milliseconds - это самая высокая точность, с которой вы хотите иметь дело, использование milliseconds в качестве типов параметров - хорошая стратегия.

Использование более грубой точности для возвращаемых типов может быть полезно для некоторых приложений , но, наверное, не для всех. Рассмотрим:

seconds process(milliseconds input);

process - это некоторая функция, которая принимает duration input, выполняет над ним некоторую операцию и возвращает результат duration. И в этом примере я выбрал более грубую точность, чем ввод (seconds). Предположительно, в какой-то момент я сократил точность ввода и в процессе потерял информацию.

Теперь, если целью process является усечение точности, это прекрасно. Но если цель process - это что-то еще, и вы просто возвращаете seconds, чтобы клиенты могли делать одно из:

milliseconds result1 = process(input);
seconds      result2 = process(input);

, тогда вы, возможно, не оказываете клиенту никаких услуг. Конечно, синтаксис для получения result2 очень чистый. Но вы также убрали выбор этого клиента по направлению усечения (вниз, вверх, ближайший и т. Д. c.). Может быть, это хорошо для вашего приложения. Но это не будет хорошо для всех, и, следовательно, не для библиотеки общего назначения.

В качестве другого примера давайте посмотрим на тип возвращаемого значения одной из функций в самой <chrono>:

template<class Rep1, class Period1, class Rep2, class Period2>
constexpr
common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>
operator+(const duration<Rep1, Period1>& lhs,
          const duration<Rep2, Period2>& rhs);

В этом примере функция (operator+) возвращает наилучшую точность из своих входных данных, в отличие от самой грубой, чтобы не потерять любую информацию. . При желании клиент может усечь этот результат. Для тех, кто не знаком с common_type_t, это соответствует:

constexpr
milliseconds
operator+(const seconds& lhs, const milliseconds& rhs);
...