From 80a142407a2d58ae7fc1fbb2f2cc71f14d6594c8 Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Sun, 16 Jul 2017 12:28:59 -0400 Subject: [PATCH] Add zoned_traits * zoned_traits is SFINEA-friendly. * zoned_traits is specialized on const time_zone* to call locate_zone. * zoned_time accesses the database via zoned_traits. * Clients with custom time zone databases can specialize zoned_traits. --- tz.h | 597 ++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 448 insertions(+), 149 deletions(-) diff --git a/tz.h b/tz.h index 6045c53..b0cc1d8 100644 --- a/tz.h +++ b/tz.h @@ -297,6 +297,57 @@ DATE_API const time_zone* locate_zone(const std::string& tz_name); DATE_API const time_zone* current_zone(); +template +struct zoned_traits +{ +}; + +template <> +struct zoned_traits +{ + static + const time_zone* + default_zone() + { + return date::locate_zone("UTC"); + } + +#if HAS_STRING_VIEW + + static + const time_zone* + locate_zone(std::string_view name) + { + return date::locate_zone(name); + } + +#else // !HAS_STRING_VIEW + + static + const time_zone* + locate_zone(const std::string& name) + { + return date::locate_zone(name); + } + + static + const time_zone* + locate_zone(const char* name) + { + return date::locate_zone(name); + } + +#endif // !HAS_STRING_VIEW +}; + +template +class zoned_time; + +template +bool +operator==(const zoned_time& x, + const zoned_time& y); + template class zoned_time { @@ -308,13 +359,36 @@ private: sys_time tp_; public: - zoned_time(); - zoned_time(const sys_time& st); + template ::default_zone())> + zoned_time(); + template ::default_zone())> + zoned_time(const sys_time& st); explicit zoned_time(TimeZonePtr z); + #if HAS_STRING_VIEW - explicit zoned_time(const std::string_view& name); + template ::locate_zone(std::string_view())) + >::value + >::type> + explicit zoned_time(std::string_view name); #else - explicit zoned_time(const std::string& name); + template ::locate_zone(std::string())) + >::value + >::type> + explicit zoned_time(const std::string& name); #endif template & zt) NOEXCEPT; zoned_time(TimeZonePtr z, const sys_time& st); - zoned_time(TimeZonePtr z, const local_time& tp); - zoned_time(TimeZonePtr z, const local_time& tp, choose c); - zoned_time(TimeZonePtr z, const zoned_time& zt); - zoned_time(TimeZonePtr z, const zoned_time& zt, choose); + + template ()->to_sys(local_time{})), + sys_time + >::value + >::type> + zoned_time(TimeZonePtr z, const local_time& tp); + + template ()->to_sys(local_time{}, + choose::earliest)), + sys_time + >::value + >::type> + zoned_time(TimeZonePtr z, const local_time& tp, choose c); + + zoned_time(TimeZonePtr z, const zoned_time& zt); + zoned_time(TimeZonePtr z, const zoned_time& zt, choose); #if HAS_STRING_VIEW - zoned_time(std::string_view name, const sys_time& st); - zoned_time(std::string_view name, const local_time& tp); - zoned_time(std::string_view name, const local_time& tp, choose c); - zoned_time(std::string_view name, const zoned_time& zt); - zoned_time(std::string_view name, const zoned_time& zt, choose); + + template ::locate_zone(std::string_view())), + sys_time + >::value + >::type> + zoned_time(std::string_view name, const sys_time& st); + + template ::locate_zone(std::string_view())), + local_time + >::value + >::type> + zoned_time(std::string_view name, const local_time& tp); + + template ::locate_zone(std::string_view())), + local_time, + choose + >::value + >::type> + zoned_time(std::string_view name, const local_time& tp, choose c); + + template ::locate_zone(std::string_view())), + zoned_time + >::value + >::type> + zoned_time(std::string_view name, const zoned_time& zt); + + template ::locate_zone(std::string_view())), + zoned_time, + choose + >::value + >::type> + zoned_time(std::string_view name, const zoned_time& zt, choose); + #else // !HAS_STRING_VIEW - zoned_time(const std::string& name, const sys_time& st); - zoned_time(const char* name, const sys_time& st); - zoned_time(const std::string& name, const local_time& tp); - zoned_time(const char* name, const local_time& tp); - zoned_time(const std::string& name, const local_time& tp, choose c); - zoned_time(const char* name, const local_time& tp, choose c); - zoned_time(const std::string& name, const zoned_time& zt); - zoned_time(const char* name, const zoned_time& zt); - zoned_time(const std::string& name, const zoned_time& zt, choose); - zoned_time(const char* name, const zoned_time& zt, choose); + + template ::locate_zone(std::string())), + sys_time + >::value + >::type> + zoned_time(const std::string& name, const sys_time& st); + + template ::locate_zone(std::string())), + sys_time + >::value + >::type> + zoned_time(const char* name, const sys_time& st); + + template ::locate_zone(std::string())), + local_time + >::value + >::type> + zoned_time(const std::string& name, const local_time& tp); + + template ::locate_zone(std::string())), + local_time + >::value + >::type> + zoned_time(const char* name, const local_time& tp); + + template ::locate_zone(std::string())), + local_time, + choose + >::value + >::type> + zoned_time(const std::string& name, const local_time& tp, choose c); + + template ::locate_zone(std::string())), + local_time, + choose + >::value + >::type> + zoned_time(const char* name, const local_time& tp, choose c); + + template ::locate_zone(std::string())), + zoned_time + >::value + >::type> + zoned_time(const std::string& name, const zoned_time& zt); + + template ::locate_zone(std::string())), + zoned_time + >::value + >::type> + zoned_time(const char* name, const zoned_time& zt); + + template ::locate_zone(std::string())), + zoned_time, + choose + >::value + >::type> + zoned_time(const std::string& name, const zoned_time& zt, choose); + + template ::locate_zone(std::string())), + zoned_time, + choose + >::value + >::type> + zoned_time(const char* name, const zoned_time& zt, choose); + #endif // !HAS_STRING_VIEW zoned_time& operator=(const sys_time& st); @@ -933,16 +1202,40 @@ DATE_API bool remote_install(const std::string& version); // zoned_time +namespace detail +{ + +template +inline +T* +to_raw_pointer(T* p) noexcept +{ + return p; +} + +template +inline +auto +to_raw_pointer(Pointer p) noexcept + -> decltype(detail::to_raw_pointer(p.operator->())) +{ + return detail::to_raw_pointer(p.operator->()); +} + +} // namespace detail + template +template inline zoned_time::zoned_time() - : zone_(locate_zone("UTC")) + : zone_(zoned_traits::default_zone()) {} template +template inline zoned_time::zoned_time(const sys_time& st) - : zone_(locate_zone("UTC")) + : zone_(zoned_traits::default_zone()) , tp_(st) {} @@ -950,25 +1243,27 @@ template inline zoned_time::zoned_time(TimeZonePtr z) : zone_(std::move(z)) - {assert(zone_ != nullptr);} + {assert(detail::to_raw_pointer(zone_) != nullptr);} -#if HAS_DEDUCTION_GUIDES +#if HAS_STRING_VIEW template +template inline -zoned_time::zoned_time(const std::string_view& name) - : zoned_time(locate_zone(name)) +zoned_time::zoned_time(std::string_view name) + : zoned_time(zoned_traits::locate_zone(name)) {} -#else +#else // !HAS_STRING_VIEW template +template inline zoned_time::zoned_time(const std::string& name) - : zoned_time(locate_zone(name)) + : zoned_time(zoned_traits::locate_zone(name)) {} -#endif +#endif // !HAS_STRING_VIEW template template @@ -980,104 +1275,36 @@ zoned_time::zoned_time(const zoned_time inline +zoned_time::zoned_time(TimeZonePtr z, const sys_time& st) + : zone_(std::move(z)) + , tp_(st) + {} + +template +template +inline zoned_time::zoned_time(TimeZonePtr z, const local_time& t) : zone_(std::move(z)) - , tp_(z->to_sys(t)) - {} - -#if HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(std::string_view name, const local_time& t) - : zoned_time(locate_zone(name), t) - {} - -#else // !HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(const std::string& name, const local_time& t) - : zoned_time(locate_zone(name), t) + , tp_(zone_->to_sys(t)) {} template -inline -zoned_time::zoned_time(const char* name, const local_time& t) - : zoned_time(locate_zone(name), t) - {} - -#endif // HAS_STRING_VIEW - -template +template inline zoned_time::zoned_time(TimeZonePtr z, const local_time& t, - choose c) + choose c) : zone_(std::move(z)) - , tp_(z->to_sys(t, c)) - {} - -#if HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(std::string_view name, const local_time& t, - choose c) - : zoned_time(locate_zone(name), t, c) - {} - -#else // !HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(const std::string& name, const local_time& t, - choose c) - : zoned_time(locate_zone(name), t, c) + , tp_(zone_->to_sys(t, c)) {} template inline -zoned_time::zoned_time(const char* name, const local_time& t, - choose c) - : zoned_time(locate_zone(name), t, c) - {} - -#endif // !HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(TimeZonePtr z, const zoned_time& zt) +zoned_time::zoned_time(TimeZonePtr z, + const zoned_time& zt) : zone_(std::move(z)) , tp_(zt.tp_) {} -#if HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(std::string_view name, - const zoned_time& zt) - : zoned_time(locate_zone(name), zt) - {} - -#else // !HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(const std::string& name, - const zoned_time& zt) - : zoned_time(locate_zone(name), zt) - {} - -template -inline -zoned_time::zoned_time(const char* name, - const zoned_time& zt) - : zoned_time(locate_zone(name), zt) - {} - -#endif // !HAS_STRING_VIEW - template inline zoned_time::zoned_time(TimeZonePtr z, @@ -1088,60 +1315,126 @@ zoned_time::zoned_time(TimeZonePtr z, #if HAS_STRING_VIEW template +template inline zoned_time::zoned_time(std::string_view name, - const zoned_time& zt, choose c) - : zoned_time(locate_zone(name), zt, c) + const sys_time& st) + : zoned_time(zoned_traits::locate_zone(name), st) + {} + +template +template +inline +zoned_time::zoned_time(std::string_view name, + const local_time& t) + : zoned_time(zoned_traits::locate_zone(name), t) + {} + +template +template +inline +zoned_time::zoned_time(std::string_view name, + const local_time& t, choose c) + : zoned_time(zoned_traits::locate_zone(name), t, c) + {} + +template +template +inline +zoned_time::zoned_time(std::string_view name, const zoned_time& zt) + : zoned_time(zoned_traits::locate_zone(name), zt) + {} + +template +template +inline +zoned_time::zoned_time(std::string_view name, + const zoned_time& zt, choose c) + : zoned_time(zoned_traits::locate_zone(name), zt, c) {} #else // !HAS_STRING_VIEW template +template inline zoned_time::zoned_time(const std::string& name, - const zoned_time& zt, choose c) - : zoned_time(locate_zone(name), zt, c) + const sys_time& st) + : zoned_time(zoned_traits::locate_zone(name), st) {} template +template inline zoned_time::zoned_time(const char* name, - const zoned_time& zt, choose c) - : zoned_time(locate_zone(name), zt, c) - {} - -#endif // !HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(TimeZonePtr z, const sys_time& st) - : zone_(std::move(z)) - , tp_(st) - {} - -#if HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(std::string_view name, const sys_time& st) - : zoned_time(locate_zone(name), st) - {} - -#else // !HAS_STRING_VIEW - -template -inline -zoned_time::zoned_time(const std::string& name, const sys_time& st) - : zoned_time(locate_zone(name), st) + const sys_time& st) + : zoned_time(zoned_traits::locate_zone(name), st) {} template +template inline -zoned_time::zoned_time(const char* name, const sys_time& st) - : zoned_time(locate_zone(name), st) +zoned_time::zoned_time(const std::string& name, + const local_time& t) + : zoned_time(zoned_traits::locate_zone(name), t) {} -#endif // !HAS_STRING_VIEW +template +template +inline +zoned_time::zoned_time(const char* name, + const local_time& t) + : zoned_time(zoned_traits::locate_zone(name), t) + {} + +template +template +inline +zoned_time::zoned_time(const std::string& name, + const local_time& t, choose c) + : zoned_time(zoned_traits::locate_zone(name), t, c) + {} + +template +template +inline +zoned_time::zoned_time(const char* name, + const local_time& t, choose c) + : zoned_time(zoned_traits::locate_zone(name), t, c) + {} + +template +template +inline +zoned_time::zoned_time(const std::string& name, + const zoned_time& zt) + : zoned_time(zoned_traits::locate_zone(name), zt) + {} + +template +template +inline +zoned_time::zoned_time(const char* name, const zoned_time& zt) + : zoned_time(zoned_traits::locate_zone(name), zt) + {} + +template +template +inline +zoned_time::zoned_time(const std::string& name, + const zoned_time& zt, choose c) + : zoned_time(zoned_traits::locate_zone(name), zt, c) + {} + +template +template +inline +zoned_time::zoned_time(const char* name, + const zoned_time& zt, choose c) + : zoned_time(zoned_traits::locate_zone(name), zt, c) + {} + +#endif // HAS_STRING_VIEW template inline @@ -1227,7 +1520,13 @@ make_zoned(const sys_time& tp) template ())>::type>{} + std::is_class + < + typename std::decay + < + decltype(*detail::to_raw_pointer(std::declval())) + >::type + >{} >::type > inline