¿Cuál es la diferencia entre chrono :: mes y chrono :: meses?

105

¿Cuál es la diferencia entre los tipos / valores de crono C ++ 20 month{7}y months{7}? ¿No es confuso tener dos nombres tan similares?

Howard Hinnant
fuente

Respuestas:

129

Sí, puede ser confuso tener ambos monthy monthscuando se encuentra por primera vez con esta biblioteca. Sin embargo, existen convenciones de nomenclatura coherentes en esta biblioteca para ayudar a reducir esa confusión. Y el beneficio es tener una clara separación de las distintas semánticas mientras se conservan los nombres intuitivos cortos.

months

Todos los chrono::durationtipos "predefinidos" son plurales:

  • nanoseconds
  • microseconds
  • milliseconds
  • seconds
  • minutes
  • hours
  • days
  • weeks
  • months
  • years

Entonces monthses un chrono::durationtipo :

usando meses = duración < tipo entero con signo de al menos 20 bits ,
                         ratio_divide <años :: período, ratio <12> >>;

Y es exactamente 1 / 12 de years.

static_assert(12*months{1} == years{1});

Puedes imprimirlo así:

cout << months{7} << '\n';

Y la salida es:

7[2629746]s

Esto se lee como 7 unidades de 2.629.746. Resulta que 2.629.746 segundos es la duración media del mes en el calendario civil. Dicho de otra manera:

static_assert(months{1} == 2'629'746s);

(el número exacto no es particularmente importante, excepto para las apuestas de barra ganadoras)

month

month(singular) por otro lado no es un chrono::duration. Es un especificador calendárico para un mes del año en el calendario civil. O:

static_assert(month{7} == July);

Esto se puede usar para formar una fecha como esta:

auto independence_day = month{7}/4d/2020y;

El álgebra de monthy monthsrefleja estas diferentes semánticas. Por ejemplo, "julio + julio" no tiene sentido y, por lo tanto, es un error en tiempo de compilación:

auto x = month{7} + month{7};
         ~~~~~~~~ ^ ~~~~~~~~
error: invalid operands to binary expression ('std::chrono::month' and 'std::chrono::month')

Pero esto tiene mucho sentido:

auto constexpr x = month{7} + months{7};
static_assert(x == February);

Y esto:

auto constexpr x = months{7} + months{7};
static_assert(x == months{14});

Y todavía:

auto b = February == months{14};
         ~~~~~~~~ ^  ~~~~~~~~~~
error: invalid operands to binary expression ('const std::chrono::month' and 'std::chrono::months')

Es decir, monthy monthsno solo no son iguales, ni siquiera son comparables. Son manzanas y naranjas, si te gustan las analogías con las frutas. ;-)

Existe una relación similar entre dayy days. Y entre yeary years.


Si es plural, es a chrono::duration.


Y solo <chrono>tiene la seguridad de tipos para ayudarlo a garantizar que estos dos conceptos semánticamente distintos pero similares no se confundan entre sí en su código.

Howard Hinnant
fuente
¿Se garantiza que sea cierto July == July + months(12*x)independientemente de x? ¿Incluso para que x sea INT_MAX?
PiotrNycz
3
Casi. Si se 12*xdesborda, tiene un comportamiento indefinido allí mismo (antes de que se monthsejecute el constructor). Sin embargo, si el valor de monthses un múltiplo de 12 (positivo o negativo), entonces sí, la suma (o resta) es esencialmente una operación no válida. Obtendría lo mismo que July == July + years(x).
Howard Hinnant
¿Hiciste tu pregunta a las 17:58 y la respondes también a las 17:58?
dejoma
2
No solo está bien responder a su propia pregunta, sino que se recomienda explícitamente: stackoverflow.blog/2011/07/01/… , stackoverflow.com/help/self-answer
Howard Hinnant