c++ - high_resolution_clock - ¿Cuál es la razón detrás de la falta de manipulación inmediata del conteo de ticks de std:: chrono:: duration?
chrono high resolution clock c++ example (4)
Supongamos que tenemos
#include <chrono>
#include <iostream>
#include <ctime>
namespace Ratios { typedef std::ratio<60*60*24,1> Days; }
typedef std::chrono::system_clock Clock;
typedef Clock::time_point TimePoint;
Y nuestro main
parece
int main(int argc, char *argv[])
{
// argc check left out for brevity
const Clock::rep d = static_cast<Clock::rep>(std::atoi(argv[1]));
// Right now
TimePoint now = Clock::now();
// Start with zero days
auto days = std::chrono::duration<Clock::rep, Ratios::Days>::zero();
// Now we''d like to add d to the days
days += d; // Error!
days.count() = d; // Error!
days = days + d; // Error!
days += std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay
days = days + std::chrono::duration<Clock::rep, Ratios::Days>(d); // Okay
days *= d; // Why is this okay?
days %= d; // And this too?
TimePoint later = now + days;
return 0;
}
¿Cuál es la razón detrás de prohibir al usuario manipular una duration
directamente?
La razón fundamental es mantener la integridad de la unidad de tiempo que representa la duration
.
Puedes pensar que el rep
no tiene unidad. Pero la duration
es una unidad de tiempo. Uno puede sumar y restar segundos a / de segundos. Pero no se pueden agregar segundos y una cantidad sin unidades sin hacer que la expresión sea ambigua y violar el álgebra de unidades.
Dicho esto, uno puede multiplicar y dividir una unidad de tiempo por una cantidad escalar (una unidad menos), y el resultado sigue siendo una unidad de tiempo. Esta biblioteca solo representa unidades de tiempo hasta la primera potencia, o potencia cero. Una unidad de tiempo elevada a la potencia cero es un escalar y está representada por rep
. Las unidades de tiempo también pueden tener un poder de 2 o más, y poderes negativos. Sin embargo, esta biblioteca no representa tales unidades.
Al sumar dos cantidades, las unidades deben ser las mismas.
Al multiplicar o dividir dos cantidades, se forma una nueva unidad (por ejemplo, km / hr). Cuando se multiplican cantidades de las mismas unidades, se agregan sus exponentes (por ejemplo, sec * sec == sec ^ 2). Cuando se dividen las cantidades de las mismas unidades, se restan sus exponentes (por ejemplo, seg./seg. == seg ^ 0 == un escalar).
La biblioteca std::chrono::duration
es un subconjunto consistente de una biblioteca de cantidades físicas que maneja solo unidades de tiempo y solo aquellas unidades de tiempo con exponentes iguales a 0 y 1.
Se hace para exigirle que se adhiera a valores fuertemente tipados en lugar de valores arbitrarios.
Bjarne Stroustrup tiene ejemplos con respecto a este comportamiento en "El lenguaje de programación C ++" (4ª edición, 35.2.1, pp. 1011):
" El período es un sistema de unidades, por lo que no hay
=
o+=
tomando un valor simple. Permitir eso sería como permitir la adición de5
de una unidad SI desconocida a una longitud en metros. Considere:
duration<long long, milli> d1{7}; // 7 milliseconds
d1 += 5; // error
[...]
¿Qué significaría 5 aquí? ¿5 segundos? 5 milisegundos? [...] Si sabes lo que quieres decir, sé explícito al respecto. Por ejemplo:
d1 += duration<long long, milli>{5}; //OK: milliseconds"
Supongo que esto se hace para obligarle a considerar cuáles son las unidades de la duración que desea agregar / restar. También le impide hacer suposiciones sobre las unidades en las que se encuentra el reloj.
days += d; // Error!
Esto se debe a que los days
variables están en unidades de 86,400 segundos y la variable d
tiene unidades. El resultado de agregar una cantidad de una unidad a un escalar sin unidad no se define en el análisis dimensional estándar.
days *= d; // Why is this okay?
days %= d; // And this too?
Porque multiplicar y dividir cantidades por escalares sin unidades no tiene sentido. Multiplicando 2 segundos por 2 resultados en 4 segundos.
Considera multiplicar 2 segundos por 3 segundos; el resultado es una cantidad 6 con la unidad ''segundos al cuadrado''. Por supuesto, chrono::duration
no es una biblioteca de unidades completa, por lo que no puede tener unidades como el tiempo al cuadrado, pero las bibliotecas como boost.units lo admitirán.