https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/95139
>From 072f4561a2ee3a48dc0754f50ecdec4dbba59421 Mon Sep 17 00:00:00 2001 From: Mark de Wever <ko...@xs4all.nl> Date: Wed, 17 Apr 2024 21:00:22 +0200 Subject: [PATCH] [libc++][TZDB] Adds zoned_time deduction guides. Completes - LWG3232 Inconsistency in zoned_time deduction guides - LWG3294 zoned_time deduction guides misinterprets stringchar* Implements parts of: - P0355 Extending to chrono Calendars and Time Zones --- libcxx/docs/Status/Cxx20Issues.csv | 4 +- libcxx/include/__chrono/zoned_time.h | 28 ++ .../time.zone.zonedtime/deduction.pass.cpp | 248 ++++++++++++++++++ 3 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 libcxx/test/std/time/time.zone/time.zone.zonedtime/deduction.pass.cpp diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index faae05d3380cc..1a40a4472a405 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -167,7 +167,7 @@ "`3218 <https://wg21.link/LWG3218>`__","Modifier for ``%d``\ parse flag does not match POSIX and ``format``\ specification","Belfast","","","|chrono| |format|" "`3224 <https://wg21.link/LWG3224>`__","``zoned_time``\ constructor from ``TimeZonePtr``\ does not specify initialization of ``tp_``\ ","Belfast","|Complete|","19.0","|chrono|" "`3230 <https://wg21.link/LWG3230>`__","Format specifier ``%y/%Y``\ is missing locale alternative versions","Belfast","|Complete|","16.0","|chrono| |format|" -"`3232 <https://wg21.link/LWG3232>`__","Inconsistency in ``zoned_time``\ deduction guides","Belfast","","","|chrono|" +"`3232 <https://wg21.link/LWG3232>`__","Inconsistency in ``zoned_time``\ deduction guides","Belfast","|Complete|","19.0","|chrono|" "`3222 <https://wg21.link/LWG3222>`__","P0574R1 introduced preconditions on non-existent parameters","Belfast","","" "`3221 <https://wg21.link/LWG3221>`__","Result of ``year_month``\ arithmetic with ``months``\ is ambiguous","Belfast","|Complete|","8.0" "`3235 <https://wg21.link/LWG3235>`__","``parse``\ manipulator without abbreviation is not callable","Belfast","","" @@ -225,7 +225,7 @@ "`3286 <https://wg21.link/LWG3286>`__","``ranges::size``\ is not required to be valid after a call to ``ranges::begin``\ on an input range","Prague","|Complete|","15.0","|ranges|" "`3291 <https://wg21.link/LWG3291>`__","``iota_view::iterator``\ has the wrong ``iterator_category``\ ","Prague","|Complete|","15.0","|ranges|" "`3292 <https://wg21.link/LWG3292>`__","``iota_view``\ is under-constrained","Prague","|Complete|","15.0","|ranges|" -"`3294 <https://wg21.link/LWG3294>`__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","Prague","","","|chrono|" +"`3294 <https://wg21.link/LWG3294>`__","``zoned_time``\ deduction guides misinterprets ``string``\ /``char*``\ ","Prague","|Complete|","19.0","|chrono|" "`3296 <https://wg21.link/LWG3296>`__","Inconsistent default argument for ``basic_regex<>::assign``\ ","Prague","|Complete|","" "`3299 <https://wg21.link/LWG3299>`__","Pointers don't need customized iterator behavior","Prague","|Complete|","15.0","|ranges|" "`3300 <https://wg21.link/LWG3300>`__","Non-array ``ssize``\ overload is underconstrained","Prague","|Nothing To Do|","" diff --git a/libcxx/include/__chrono/zoned_time.h b/libcxx/include/__chrono/zoned_time.h index 101a9f52966ad..7a13c4e3a3dee 100644 --- a/libcxx/include/__chrono/zoned_time.h +++ b/libcxx/include/__chrono/zoned_time.h @@ -25,6 +25,8 @@ # include <__config> # include <__fwd/string_view.h> # include <__type_traits/common_type.h> +# include <__type_traits/conditional.h> +# include <__type_traits/remove_cvref.h> # include <__utility/move.h> # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -177,6 +179,32 @@ class zoned_time { sys_time<duration> __tp_; }; +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_cvref_t<_TimeZonePtrOrName>>; + +template <class _TimeZonePtrOrName> +zoned_time(_TimeZonePtrOrName&&) -> zoned_time<seconds, __time_zone_representation<_TimeZonePtrOrName>>; + +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 _Duration, class _TimeZonePtrOrName, class TimeZonePtr2> +zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, TimeZonePtr2>, choose = choose::earliest) + -> zoned_time<common_type_t<_Duration, seconds>, __time_zone_representation<_TimeZonePtrOrName>>; + } // namespace chrono # endif // _LIBCPP_STD_VER >= 20 && !defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) && !defined(_LIBCPP_HAS_NO_FILESYSTEM) diff --git a/libcxx/test/std/time/time.zone/time.zone.zonedtime/deduction.pass.cpp b/libcxx/test/std/time/time.zone/time.zone.zonedtime/deduction.pass.cpp new file mode 100644 index 0000000000000..3595d0a5f917e --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/deduction.pass.cpp @@ -0,0 +1,248 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: no-filesystem, no-localization, no-tzdb + +// XFAIL: libcpp-has-no-experimental-tzdb +// XFAIL: availability-tzdb-missing + +// <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 = // exposition only +// conditional_t<is_convertible_v<TimeZonePtrOrName, string_view>, +// const time_zone*, +// remove_cvref_t<TimeZonePtrOrName>>; +// +// template<class TimeZonePtrOrName> +// zoned_time(TimeZonePtrOrName&&) +// -> zoned_time<seconds, time-zone-representation<TimeZonePtrOrName>>; +// +// 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 Duration, class TimeZonePtrOrName, class TimeZonePtr2> +// zoned_time(TimeZonePtrOrName&&, zoned_time<Duration, TimeZonePtr2>, +// choose = choose::earliest) +// -> zoned_time<common_type_t<Duration, seconds>, +// time-zone-representation<TimeZonePtrOrName>>; + +#include <chrono> +#include <concepts> +#include <string> + +#include "test_offset_time_zone.h" + +namespace cr = std::chrono; + +// Verify the results of the constructed object. +int main(int, char**) { + { + // zoned_time() -> zoned_time<seconds>; + cr::zoned_time zt; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + + { + // template<class Duration> + // zoned_time(sys_time<Duration>) + // -> zoned_time<common_type_t<Duration, seconds>>; + { + cr::zoned_time zt{cr::sys_time<cr::nanoseconds>{cr::nanoseconds{0}}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{cr::sys_time<cr::seconds>{cr::seconds{0}}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{cr::sys_time<cr::days>{cr::days{0}}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + + { + // template<class TimeZonePtrOrName> + // zoned_time(TimeZonePtrOrName&&) + // -> zoned_time<seconds, time-zone-representation<TimeZonePtrOrName>>; + { // Name + { + cr::zoned_time zt{"UTC"}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{std::string{"UTC"}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{std::string_view{"UTC"}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + { // TimeZonePtr + { + cr::zoned_time zt{static_cast<const cr::time_zone*>(nullptr)}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{offset_time_zone<offset_time_zone_flags::none>{}}; + static_assert( + std::same_as< decltype(zt), cr::zoned_time<cr::seconds, offset_time_zone<offset_time_zone_flags::none>>>); + } + { + cr::zoned_time zt{offset_time_zone<offset_time_zone_flags::has_default_zone>{}}; + static_assert( + std::same_as<decltype(zt), + cr::zoned_time<cr::seconds, offset_time_zone<offset_time_zone_flags::has_default_zone>>>); + } + { + cr::zoned_time zt{offset_time_zone<offset_time_zone_flags::has_locate_zone>{}}; + static_assert( + std::same_as<decltype(zt), + cr::zoned_time<cr::seconds, offset_time_zone<offset_time_zone_flags::has_locate_zone>>>); + } + { + cr::zoned_time zt{offset_time_zone<offset_time_zone_flags::both>{}}; + static_assert( + std::same_as< decltype(zt), cr::zoned_time<cr::seconds, offset_time_zone<offset_time_zone_flags::both>>>); + } + + // There are no requirements on the TimeZonePtr type. + { + cr::zoned_time zt{0}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, int>>); + } + { + cr::zoned_time zt{0.0}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, double>>); + } + { + cr::zoned_time zt{cr::seconds{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, cr::seconds>>); + } + } + } + + { + // template<class TimeZonePtrOrName, class Duration> + // zoned_time(TimeZonePtrOrName&&, sys_time<Duration>) + // -> zoned_time<common_type_t<Duration, seconds>, + // time-zone-representation<TimeZonePtrOrName>>; + { // Name + { + cr::zoned_time zt{"UTC", cr::sys_time<cr::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{"UTC", cr::sys_time<cr::days>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + + { // TimeZonePtr + { + cr::zoned_time zt{static_cast<const cr::time_zone*>(nullptr), cr::sys_time<cr::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{static_cast<const cr::time_zone*>(nullptr), cr::sys_time<cr::days>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{offset_time_zone<offset_time_zone_flags::none>{}, cr::sys_time<cr::nanoseconds>{}}; + static_assert(std::same_as< decltype(zt), + cr::zoned_time<cr::nanoseconds, offset_time_zone<offset_time_zone_flags::none>>>); + } + { + cr::zoned_time zt{offset_time_zone<offset_time_zone_flags::none>{}, cr::sys_time<cr::days>{}}; + static_assert( + std::same_as< decltype(zt), cr::zoned_time<cr::seconds, offset_time_zone<offset_time_zone_flags::none>>>); + } + } + } + + { + // 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>>; + { // Name + { + cr::zoned_time zt{"UTC", cr::local_time<cr::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{"UTC", cr::local_time<cr::days>{}, cr::choose::earliest}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + { // TimeZonePtr + { + cr::zoned_time zt{cr::locate_zone("UTC"), cr::local_time<cr::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{cr::locate_zone("UTC"), cr::local_time<cr::days>{}, cr::choose::earliest}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + } + + { + // template<class Duration, class TimeZonePtrOrName, class TimeZonePtr2> + // zoned_time(TimeZonePtrOrName&&, zoned_time<Duration, TimeZonePtr2>, + // choose = choose::earliest) + // -> zoned_time<common_type_t<Duration, seconds>, + // time-zone-representation<TimeZonePtrOrName>>; + { // Name + { + cr::zoned_time zt{ + "UTC", cr::zoned_time<cr::nanoseconds, offset_time_zone<offset_time_zone_flags::has_default_zone>>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{"UTC", + cr::zoned_time<cr::days, offset_time_zone<offset_time_zone_flags::has_default_zone>>{}, + cr::choose::earliest}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + { // TimeZonePtr + { + cr::zoned_time zt{ + cr::locate_zone("UTC"), + cr::zoned_time<cr::nanoseconds, offset_time_zone<offset_time_zone_flags::has_default_zone>>{}}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::nanoseconds, const cr::time_zone*>>); + } + { + cr::zoned_time zt{cr::locate_zone("UTC"), + cr::zoned_time<cr::days, offset_time_zone<offset_time_zone_flags::has_default_zone>>{}, + cr::choose::earliest}; + static_assert(std::same_as<decltype(zt), cr::zoned_time<cr::seconds, const cr::time_zone*>>); + } + } + } + + return 0; +} _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits