4139. §[time.zone.leap] recursive constraint in <=>

Section: 30.11.8 [time.zone.leap] Status: New Submitter: Corentin Opened: 2024-08-18 Last modified: 2024-08-21

Priority: 3

View all other issues in [time.zone.leap].

View all issues with New status.

Discussion:

Consider

decltype(std::declval<std::chrono::leap_second&>() <=> std::chrono::system_clock::now())

There is a <=> operator for leap second defined as

template<class Duration>
  requires three_way_comparable_with<sys_seconds, sys_time<Duration>>
  constexpr auto operator<=>(const leap_second& x, const sys_time<Duration>& y) noexcept;

In order to resolve this overload, we need to check the constraints. three_way_comparable_with will end up checking that sys_seconds{} < sys_time<Duration>{} is a valid expression. To do that, we run overload resolution, find a bunch of operator<=>, including the leap_second overload mentioned above. We check its constraints... and we find ourselves doing that recursively.

This problem currently doesn't manifest in production compilers because of a number of non-conforming behaviors of all implementations, but surfaced while fixing some of these issues in clang.

libstdc++ also does not suffer from this issue because leap_seconds comparisons operators are all hidden friends (in fact, libstdc++ define hidden friends comparison operators for most of the objects in chrono, which is nice!)

Suggested resolution:

Specify that leap_seconds operators are hidden friends. This would avoid the recursion, and would be easier on compilers.

[2024-08-21; Reflector poll]

Set priority to 3 after reflector poll. Support for changing all relational ops for calendar types to hidden friends, but only doing it for leap_second would be in scope for this issue.

Proposed resolution: