What is the difference between the C++20 chrono types/values month{7}
and months{7}
? Isn't it confusing to have two such similar names?
Class template std::chrono::duration represents a time interval. It consists of a count of ticks of type Rep and a tick period, where the tick period is a compile-time rational fraction representing the time in seconds from one tick to the next. The only data stored in a duration is a tick count of type Rep .
Chrono in C++ chrono is the name of a header and also of a sub-namespace: All the elements in this header (except for the common_type specializations) are not defined directly under the std namespace (like most of the standard library) but under the std::chrono namespace. The elements in this header deal with time.
Yes, it can be confusing to have both month
and months
when first encountering this library. However there are consistent naming conventions in this library to help reduce that confusion. And the benefit is having a clear separation of distinct semantics while retaining short intuitive names.
months
All "predefined" chrono::duration
types are plural:
nanoseconds
microseconds
milliseconds
seconds
minutes
hours
days
weeks
months
years
So months
is a chrono::duration
type:
using months = duration<signed integer type of at least 20 bits, ratio_divide<years::period, ratio<12>>>;
And it is exactly 1/12 of years
.
static_assert(12*months{1} == years{1});
You can print it out like this:
cout << months{7} << '\n';
And the output is:
7[2629746]s
This reads as 7 units of 2,629,746s. It turns out that 2,629,746 seconds is the average length of the month in the civil calendar. Stated differently:
static_assert(months{1} == 2'629'746s);
(the exact number is not particularly important except for winning bar bets)
month
month
(singular) on the other hand is not a chrono::duration
. It is a calendrical specifier for a month of the year in the civil calendar. Or:
static_assert(month{7} == July);
This can be used to form a date like this:
auto independence_day = month{7}/4d/2020y;
The algebra of month
and months
reflect these different semantics. For example "July + July" is nonsensical, and thus a compile-time error:
auto x = month{7} + month{7}; ~~~~~~~~ ^ ~~~~~~~~ error: invalid operands to binary expression ('std::chrono::month' and 'std::chrono::month')
But this makes perfect sense:
auto constexpr x = month{7} + months{7}; static_assert(x == February);
And this:
auto constexpr x = months{7} + months{7}; static_assert(x == months{14});
And yet:
auto b = February == months{14}; ~~~~~~~~ ^ ~~~~~~~~~~ error: invalid operands to binary expression ('const std::chrono::month' and 'std::chrono::months')
I.e. month
and months
are not only not-equal, they are not even comparable. They are apples and oranges, if you're into fruit analogies. ;-)
There is a similar relationship between day
and days
. And between year
and years
.
If it is plural, it is a
chrono::duration
.
And only <chrono>
has the type safety to help you ensure that these two semantically distinct and yet similar concepts do not get confused with one another in your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With