zoned_time deduction guides misinterprets string/char*Section: 30.11.7.1 [time.zone.zonedtime.overview] Status: C++20 Submitter: Tomasz Kamiński Opened: 2019-09-14 Last modified: 2021-02-25
Priority: 0
View all other issues in [time.zone.zonedtime.overview].
View all issues with C++20 status.
Discussion:
The current deduction guide for zoned_time for the following declarations
zoned_time zpc("America/New_York", std::chrono::system_clock::now());
zoned_time zps(std::string("America/New_York"), std::chrono::system_clock::now());
will attempt to produce a zoned_time instance with const char*
(for zpc) and with std::string (for zps), respectively,
as the deduced type for the TimeZonePtr template parameter. This is caused by
the fact that the unconstrained TimeZonePtr deduction guide template will
produce better candidates and will be selected by overload resolution.
std::string_view/TimeZonePtr deduction guides
into one guide, that deduces const time_zone* for any type
convertible to string_view. This is necessary to override
the deduction from TimeZonePtr constructor candidates.
In addition, we disable the deduction from string_view
constructors, that would produce better candidates than the deduction guides
and create zoned_time instances with durations coarser than
seconds (causing similar issue as LWG 3232):
std::chrono::local_time<hours> lh(10h);
std::chrono::zoned_time zt1("Europe/Helsinki", lh);
std::chrono::zoned_time zt2(std::string("Europe/Helsinki"), lh);
std::chrono::zoned_time zt3(std::string_view("Europe/Helsinki"), lh);
Without disabling the deduction from the string_view
constructor, the type of the zt3 variable would be deduced to
zoned_time<hours>, with the proposed change the types
of the variables zt1, zt2, and zt3
are consistently deduced as zoned_time<seconds>.
zoned_time<Duration>
guide (covered by zoned_time<Duration, TimeZonePtr2>).
The change was implemented in the example implementation. The dedicated
test can be found
here.
[2019-10-31 Issue Prioritization]
Status to Tentatively Ready and priority to 0 after five positive votes on the reflector.
Proposed resolution:
This wording is relative to N4830.
Modify 30.11.7.1 [time.zone.zonedtime.overview], class template zoned_time
synopsis, as indicated:
namespace std::chrono { […] zoned_time() -> zoned_time<seconds>; template<class Duration> zoned_time(sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>>; template<class TimeZonePtrOrName> using time-zone-representation = conditional_t<is_convertible_v<TimeZonePtrOrName, string_view>, const time_zone*, remove_cv_ref<TimeZonePtrOrName>>; // exposition only template<class TimeZonePtrOrName> zoned_time(TimeZonePtrOrName&&) -> zoned_time<seconds, time-zone-representation<TimeZonePtr>>; template<class TimeZonePtrOrName, class Duration> zoned_time(TimeZonePtrOrName&&, sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>, time-zone-representation<TimeZonePtrOrName>>; template<class TimeZonePtrOrName, class Duration> zoned_time(TimeZonePtrOrName&&, local_time<Duration>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>, time-zone-representation<TimeZonePtrOrName>>;template<class TimeZonePtr, class Duration> zoned_time(TimeZonePtr, zoned_time<Duration>, choose = choose::earliest) ->> zoned_time<common_type_t<Duration, seconds>, TimeZonePtr>; zoned_time(string_view) -> zoned_time<seconds>; template<class Duration> zoned_time(string_view, sys_time<Duration>) -> zoned_time<common_type_t<Duration, seconds>>; template<class Duration> zoned_time(string_view, local_time<Duration>, choose = choose::earliest) -> zoned_time<common_type_t<Duration, seconds>>;template<class Duration, class TimeZonePtrOrName, class TimeZonePtr2> zoned_time(TimeZonePtrOrName&&, zoned_time<Duration, TimeZonePtr2>, choose = choose::earliest) -> zoned_time<Duration, time-zone-representation<TimeZonePtrOrName>>; }-1-
-2- Ifzoned_timerepresents a logical pairing of atime_zoneand atime_pointwith precisionDuration.zoned_time<Duration>maintains the invariant that it always refers to a valid time zone and represents a point in time that exists and is not ambiguous in that time zone.Durationis not a specialization ofchrono::duration, the program is ill-formed. -?- Every constructor ofzoned_timethat accepts astring_viewas first parameter does not participate in class template argument deduction (12.2.2.9 [over.match.class.deduct]).