llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libcxx Author: Mark de Wever (mordante) <details> <summary>Changes</summary> 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 --- Full diff: https://github.com/llvm/llvm-project/pull/95139.diff 3 Files Affected: - (modified) libcxx/docs/Status/Cxx20Issues.csv (+2-2) - (modified) libcxx/include/__chrono/zoned_time.h (+28) - (added) libcxx/test/std/time/time.zone/time.zone.zonedtime/deduction.pass.cpp (+285) ``````````diff diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index 5051a2089c98e..a288d1add33e2 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 169efb8e9d6f3..33e0ac0603a6e 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) @@ -176,6 +178,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..b64dbebd235b1 --- /dev/null +++ b/libcxx/test/std/time/time.zone/time.zone.zonedtime/deduction.pass.cpp @@ -0,0 +1,285 @@ +//===----------------------------------------------------------------------===// +// +// 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" + +// Verify the results of the constructed object. +int main(int, char**) { + { + // zoned_time() -> zoned_time<seconds>; + std::chrono::zoned_time zt; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + + { + // template<class Duration> + // zoned_time(sys_time<Duration>) + // -> zoned_time<common_type_t<Duration, seconds>>; + { + std::chrono::zoned_time zt{std::chrono::sys_time<std::chrono::nanoseconds>{std::chrono::nanoseconds{0}}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{std::chrono::sys_time<std::chrono::seconds>{std::chrono::seconds{0}}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{std::chrono::sys_time<std::chrono::days>{std::chrono::days{0}}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + } + + { + // template<class TimeZonePtrOrName> + // zoned_time(TimeZonePtrOrName&&) + // -> zoned_time<seconds, time-zone-representation<TimeZonePtrOrName>>; + { // Name + { + std::chrono::zoned_time zt{"UTC"}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{std::string{"UTC"}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{std::string_view{"UTC"}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + } + { // TimeZonePtr + { + std::chrono::zoned_time zt{static_cast<const std::chrono::time_zone*>(nullptr)}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::none>{}}; + static_assert(std::same_as< + decltype(zt), + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::none>>>); + } + { + std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::has_default_zone>{}}; + static_assert( + std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::seconds, + offset_time_zone<offset_time_zone_flags::has_default_zone>>>); + } + { + std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::has_locate_zone>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::seconds, + offset_time_zone<offset_time_zone_flags::has_locate_zone>>>); + } + { + std::chrono::zoned_time zt{offset_time_zone<offset_time_zone_flags::both>{}}; + static_assert(std::same_as< + decltype(zt), + std::chrono::zoned_time<std::chrono::seconds, offset_time_zone<offset_time_zone_flags::both>>>); + } + + // There are no requirements on the TimeZonePtr type. + { + std::chrono::zoned_time zt{0}; + static_assert(std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, int>>); + } + { + std::chrono::zoned_time zt{0.0}; + static_assert(std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, double>>); + } + { + std::chrono::zoned_time zt{std::chrono::seconds{}}; + static_assert(std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, std::chrono::seconds>>); + } + } + } + + { + // template<class TimeZonePtrOrName, class Duration> + // zoned_time(TimeZonePtrOrName&&, sys_time<Duration>) + // -> zoned_time<common_type_t<Duration, seconds>, + // time-zone-representation<TimeZonePtrOrName>>; + { // Name + { + std::chrono::zoned_time zt{"UTC", std::chrono::sys_time<std::chrono::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{"UTC", std::chrono::sys_time<std::chrono::days>{}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + } + + { // TimeZonePtr + { + std::chrono::zoned_time zt{ + static_cast<const std::chrono::time_zone*>(nullptr), std::chrono::sys_time<std::chrono::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{ + static_cast<const std::chrono::time_zone*>(nullptr), std::chrono::sys_time<std::chrono::days>{}}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{ + offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_time<std::chrono::nanoseconds>{}}; + static_assert( + std::same_as< + decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, offset_time_zone<offset_time_zone_flags::none>>>); + } + { + std::chrono::zoned_time zt{ + offset_time_zone<offset_time_zone_flags::none>{}, std::chrono::sys_time<std::chrono::days>{}}; + static_assert(std::same_as< + decltype(zt), + std::chrono::zoned_time<std::chrono::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 + { + std::chrono::zoned_time zt{"UTC", std::chrono::local_time<std::chrono::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{"UTC", std::chrono::local_time<std::chrono::days>{}, std::chrono::choose::earliest}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + } + { // TimeZonePtr + { + std::chrono::zoned_time zt{ + std::chrono::locate_zone("UTC"), std::chrono::local_time<std::chrono::nanoseconds>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{ + std::chrono::locate_zone("UTC"), + std::chrono::local_time<std::chrono::days>{}, + std::chrono::choose::earliest}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::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 + { + std::chrono::zoned_time zt{ + "UTC", + std::chrono::zoned_time<std::chrono::nanoseconds, + offset_time_zone<offset_time_zone_flags::has_default_zone>>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{ + "UTC", + std::chrono::zoned_time<std::chrono::days, offset_time_zone<offset_time_zone_flags::has_default_zone>>{}, + std::chrono::choose::earliest}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + } + { // TimeZonePtr + { + std::chrono::zoned_time zt{ + std::chrono::locate_zone("UTC"), + std::chrono::zoned_time<std::chrono::nanoseconds, + offset_time_zone<offset_time_zone_flags::has_default_zone>>{}}; + static_assert(std::same_as<decltype(zt), + std::chrono::zoned_time<std::chrono::nanoseconds, const std::chrono::time_zone*>>); + } + { + std::chrono::zoned_time zt{ + std::chrono::locate_zone("UTC"), + std::chrono::zoned_time<std::chrono::days, offset_time_zone<offset_time_zone_flags::has_default_zone>>{}, + std::chrono::choose::earliest}; + static_assert( + std::same_as<decltype(zt), std::chrono::zoned_time<std::chrono::seconds, const std::chrono::time_zone*>>); + } + } + } + + return 0; +} `````````` </details> https://github.com/llvm/llvm-project/pull/95139 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits