Chrono: : month 和 Chrono: : mons 之间的区别是什么

C + + 20 Chrono 类型/值 month{7}months{7}有什么不同?有两个这么相似的名字,是不是很让人困惑?

5193 次浏览

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.