Jaka jest różnica między chrono :: month i chrono :: months

106

Jaka jest różnica między typami / wartościami chronologicznymi C ++ 20 month{7}a months{7}? Czy nie jest mylące mieć dwie takie podobne nazwy?

Howard Hinnant
źródło

Odpowiedzi:

130

Tak, posiadanie obu monthi monthsprzy pierwszym kontakcie z tą biblioteką może być mylące . Jednak w tej bibliotece obowiązują spójne konwencje nazewnictwa, które pomagają zmniejszyć to zamieszanie. Zaletą jest wyraźne oddzielenie odrębnych semantyki przy zachowaniu krótkich, intuicyjnych nazw.

months

Wszystkie „predefiniowane” chrono::durationtypy są w liczbie mnogiej:

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

Więc monthsjest chrono::durationtyp :

przy użyciu miesięcy = czas trwania < typ liczby całkowitej ze znakiem co najmniej 20 bitów ,
                         ratio_divide <lata :: okres, stosunek <12> >>;

I to jest dokładnie 1 / 12 z years.

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

Możesz to wydrukować w ten sposób:

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

A wynik to:

7[2629746]s

To czyta się jako 7 jednostek 2629746s. Okazuje się, że 2629746 sekund to średnia długość miesiąca w kalendarzu cywilnym. Stwierdzono inaczej:

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

(dokładna liczba nie jest szczególnie ważna, z wyjątkiem wygrywających zakładów barowych)

month

month(liczba pojedyncza) z drugiej strony nie jest chrono::duration. Jest to specyfikator kalendarzowy miesiąca w roku w kalendarzu cywilnym. Lub:

static_assert(month{7} == July);

Można to wykorzystać do utworzenia takiej daty:

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

Algebra monthi monthsodzwierciedlają te różne semantyki. Na przykład „lipiec + lipiec” jest bezsensowne, a zatem stanowi błąd w czasie kompilacji:

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

Ale to ma sens:

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

I to:

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

I jeszcze:

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

Tj. monthI monthsnie tylko nie są równe, ale nie są nawet porównywalne. To jabłka i pomarańcze, jeśli lubisz owocowe analogie. ;-)

Istnieje podobny związek między dayi days. A między yeara years.


Jeśli jest w liczbie mnogiej, to jest chrono::duration.


I <chrono>ma tylko bezpieczeństwo typów, które pomaga zapewnić, że te dwa semantycznie różne, a jednocześnie podobne koncepcje nie zostaną pomylone ze sobą w kodzie.

Howard Hinnant
źródło
Czy jest to prawdą July == July + months(12*x)niezależnie od x? Nawet jeśli x jest INT_MAX?
PiotrNycz
3
Prawie. Jeśli 12*xprzepełnienia, masz niezdefiniowane zachowanie (przed monthsuruchomieniem konstruktora). Jeśli jednak wartość monthsjest wielokrotnością 12 (dodatnia lub ujemna), to tak, dodawanie (lub odejmowanie) jest zasadniczo niedopuszczalne. Dostałbyś to samo, co July == July + years(x).
Howard Hinnant
Zadałeś pytanie 17:58 i odpowiadasz również o 17:58?
dejoma
2
Odpowiedź na własne pytanie jest nie tylko w porządku, ale wręcz zachęcamy: stackoverflow.blog/2011/07/01/… , stackoverflow.com/help/self-answer
Howard Hinnant