This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4067. Inconsistency and potential infinity meta-recursion in std::chrono::zoned_time's constructors

Section: 29.11.7.2 [time.zone.zonedtime.ctor] Status: New Submitter: Jiang An Opened: 2024-04-14 Last modified: 2024-04-15

Priority: Not Prioritized

View all other issues in [time.zone.zonedtime.ctor].

View all issues with New status.

Discussion:

Currently, there are no requirements on a program-defined std::chrono::zoned_traits specialization. So a zoned_traits<UserDefinedTzPtr>::locate_zone possibly returns a string_view, which leads to infinite meta-recursion when checking the constraints of zoned_time's constructors that take a string_view.

Also, the constructor of zoned_time taking only one string_view is inconsistent with others and even self-inconsistent. For other constructors taking string_view, it is expected that the return value of locate_zone is only implicitly converted to a TimeZonePtr. But the return value is permitted to be convertible to zoned_time or sys_time<Duration> in this constructor. And given the locate_name function may be an overload set that distinguishes lvalues and rvalues of string_view, the use of locate_time(string_view{}) in the constraints doesn't always reflect locate_time(name) in the effects as the return types can be different.

Proposed resolution:

This wording is relative to N4971.

  1. Modify 29.11.7.2 [time.zone.zonedtime.ctor] as indicated:

    [Drafting note: Add the following two paragraphs to the very beginning of subclause 29.11.7.2 [time.zone.zonedtime.ctor]]

    -?- Let locatable-as-tzptr be true if given an lvalue sv of type string_view, traits::locate_zone(sv) is well-formed and TimeZonePtr is implicitly convertible from its return type, and false otherwise. Only the validity of the immediate context of the invocation and conversion is considered.

    -?- In every constructor that takes a string_view parameter name, let converted-tzptr be a variable of type TimeZonePtr that is copy-initialized from traits::locate_zone(name).

    […]

    explicit zoned_time(string_view name);
    

    -7- Constraints: traits::locate_zone(string_view{}) is a well-formed expression and zoned_time is constructible from the return type of traits::locate_zone(string_view{}) locatable-as-tzptr is true.

    -8- Effects: Initializes zone_ with traits::locate_zone(name) and default constructs tp_.

    […]

    zoned_time(string_view name, const sys_time<Duration>& st);
    

    -13- Constraints: zoned_time is constructible from the return type of traits::locate_zone(name) and stlocatable-as-tzptr is true.

    -14- Effects: Equivalent to construction with {traits::locate_zone(name)std::move(converted-tzptr), st}.

    […]

    zoned_time(string_view name, const local_time<Duration>& tp);
    

    -18- Constraints: locatable-as-tzptr is true and zoned_time is constructible from the return type of traits::locate_zone(name)TimeZonePtr and tp.

    -19- Effects: Equivalent to construction with {traits::locate_zone(name)std::move(converted-tzptr), tp}.

    […]

    zoned_time(string_view name, const local_time<Duration>& tp, choose c);
    

    -23- Constraints: locatable-as-tzptr is true and zoned_time is constructible from the return type of traits::locate_zone(name)TimeZonePtr, local_time<Duration>, and choose.

    -24- Effects: Equivalent to construction with {traits::locate_zone(name)std::move(converted-tzptr), tp, c}.

    […]

    template<class Duration2, class TimeZonePtr2>
      zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y);
    

    -32- Constraints: locatable-as-tzptr is true and zoned_time is constructible from the return type of traits::locate_zone(name)TimeZonePtr and the type zoned_time<Duration2, TimeZonePtr2>.

    -33- Effects: Equivalent to construction with {traits::locate_zone(name)std::move(converted-tzptr), y}.

    template<class Duration2, class TimeZonePtr2>
      zoned_time(string_view name, const zoned_time<Duration2, TimeZonePtr2>& y, choose c);
    

    -34- Constraints: locatable-as-tzptr is true and zoned_time is constructible from the return type of traits::locate_zone(name)TimeZonePtr, the type zoned_time<Duration2, TimeZonePtr2>, and the type choose.

    -35- Effects: Equivalent to construction with {traits::locate_zone(name)std::move(converted-tzptr), y, c}.