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_time
represents a logical pairing of atime_zone
and atime_point
with 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.Duration
is not a specialization ofchrono::duration
, the program is ill-formed. -?- Every constructor ofzoned_time
that accepts astring_view
as first parameter does not participate in class template argument deduction (12.2.2.9 [over.match.class.deduct]).