@@ -1712,7 +1712,7 @@ namespace chrono {
17121712
17131713 template <class _Duration>
17141714 [[noreturn]] void _Throw_nonexistent_local_time(const local_time<_Duration>& _Tp, const local_info& _Info) {
1715- _THROW(( nonexistent_local_time{_Tp, _Info}) );
1715+ _THROW(nonexistent_local_time{_Tp, _Info});
17161716 }
17171717
17181718 _EXPORT_STD class ambiguous_local_time : public runtime_error {
@@ -1735,16 +1735,39 @@ namespace chrono {
17351735
17361736 template <class _Duration>
17371737 [[noreturn]] void _Throw_ambiguous_local_time(const local_time<_Duration>& _Tp, const local_info& _Info) {
1738- _THROW(( ambiguous_local_time{_Tp, _Info}) );
1738+ _THROW(ambiguous_local_time{_Tp, _Info});
17391739 }
17401740
17411741 // [time.zone.timezone]
17421742
1743+ template <auto& _Get_tzdb_info, class... _Types>
1744+ _NODISCARD auto _Make_unique_tzdb_info(_Types&&... _Args) {
1745+ const auto _Raw_ptr = _Get_tzdb_info(_STD forward<_Types>(_Args)...);
1746+
1747+ using _Tzdb_info = remove_pointer_t<decltype(_Raw_ptr)>;
1748+
1749+ unique_ptr<_Tzdb_info, _Tzdb_deleter<_Tzdb_info>> _Info{_Raw_ptr};
1750+
1751+ if (_Info == nullptr) {
1752+ _Xbad_alloc();
1753+ } else if (_Info->_Err == __std_tzdb_error::_Win_error) {
1754+ _XGetLastError();
1755+ } else if (_Info->_Err == __std_tzdb_error::_Icu_error) {
1756+ _Xruntime_error("Internal error loading IANA database information");
1757+ }
1758+
1759+ return _Info;
1760+ }
1761+
17431762 _EXPORT_STD enum class choose { earliest, latest };
17441763
1764+ struct _Secret_time_zone_construct_tag {
1765+ explicit _Secret_time_zone_construct_tag() = default;
1766+ };
1767+
17451768 _EXPORT_STD class time_zone {
17461769 public:
1747- explicit time_zone(string_view _Name_) : _Name(_Name_) {}
1770+ explicit time_zone(_Secret_time_zone_construct_tag, string_view _Name_) : _Name(_Name_) {}
17481771
17491772 time_zone(time_zone&&) = default;
17501773 time_zone& operator=(time_zone&&) = default;
@@ -1811,16 +1834,8 @@ namespace chrono {
18111834
18121835 const auto _Tz_len = _Name.length();
18131836
1814- const unique_ptr<__std_tzdb_sys_info, _Tzdb_deleter<__std_tzdb_sys_info>> _Info{
1815- __std_tzdb_get_sys_info(_Tz_arg.c_str(), _Tz_len, _Internal_dur.count())};
1816-
1817- if (_Info == nullptr) {
1818- _Xbad_alloc();
1819- } else if (_Info->_Err == __std_tzdb_error::_Win_error) {
1820- _XGetLastError();
1821- } else if (_Info->_Err == __std_tzdb_error::_Icu_error) {
1822- _Xruntime_error("Internal error loading IANA database information");
1823- }
1837+ const auto _Info =
1838+ _Make_unique_tzdb_info<__std_tzdb_get_sys_info>(_Tz_arg.c_str(), _Tz_len, _Internal_dur.count());
18241839
18251840 constexpr auto _Min_internal =
18261841 _CHRONO duration_cast<_Internal_duration>(_Min_seconds.time_since_epoch()).count();
@@ -2012,9 +2027,14 @@ namespace chrono {
20122027
20132028 // [time.zone.link]
20142029
2030+ struct _Secret_time_zone_link_construct_tag {
2031+ explicit _Secret_time_zone_link_construct_tag() = default;
2032+ };
2033+
20152034 _EXPORT_STD class time_zone_link {
20162035 public:
2017- explicit time_zone_link(string_view _Name_, string_view _Target_) : _Name(_Name_), _Target(_Target_) {}
2036+ explicit time_zone_link(_Secret_time_zone_link_construct_tag, string_view _Name_, string_view _Target_)
2037+ : _Name(_Name_), _Target(_Target_) {}
20182038
20192039 time_zone_link(time_zone_link&&) = default;
20202040 time_zone_link& operator=(time_zone_link&&) = default;
@@ -2046,17 +2066,9 @@ namespace chrono {
20462066 // [time.zone.db]
20472067
20482068 _NODISCARD inline string _Tzdb_generate_current_zone() {
2049- unique_ptr<__std_tzdb_current_zone_info, _Tzdb_deleter<__std_tzdb_current_zone_info>> _Info{
2050- __std_tzdb_get_current_zone()};
2051- if (_Info == nullptr) {
2052- _Xbad_alloc();
2053- } else if (_Info->_Err == __std_tzdb_error::_Win_error) {
2054- _XGetLastError();
2055- } else if (_Info->_Err == __std_tzdb_error::_Icu_error) {
2056- _Xruntime_error("Internal error loading IANA database information");
2057- }
2069+ auto _Info = _Make_unique_tzdb_info<__std_tzdb_get_current_zone>();
20582070
2059- return { _Info->_Tz_name} ;
2071+ return _Info->_Tz_name;
20602072 }
20612073
20622074 template <class _Ty>
@@ -2094,26 +2106,18 @@ namespace chrono {
20942106 }
20952107 };
20962108
2097- _NODISCARD inline tuple<string, decltype(tzdb::zones), decltype(tzdb::links)> _Tzdb_generate_time_zones() {
2098- unique_ptr<__std_tzdb_time_zones_info, _Tzdb_deleter<__std_tzdb_time_zones_info>> _Info{
2099- __std_tzdb_get_time_zones()};
2100- if (_Info == nullptr) {
2101- _Xbad_alloc();
2102- } else if (_Info->_Err == __std_tzdb_error::_Win_error) {
2103- _XGetLastError();
2104- } else if (_Info->_Err == __std_tzdb_error::_Icu_error) {
2105- _Xruntime_error("Internal error loading IANA database information");
2106- }
2109+ _NODISCARD inline tuple<string, vector<time_zone>, vector<time_zone_link>> _Tzdb_generate_time_zones() {
2110+ auto _Info = _Make_unique_tzdb_info<__std_tzdb_get_time_zones>();
21072111
2108- decltype(tzdb::zones) _Time_zones;
2109- decltype(tzdb::links) _Time_zone_links;
2112+ vector<time_zone> _Time_zones;
2113+ vector<time_zone_link> _Time_zone_links;
21102114 for (size_t _Idx = 0; _Idx < _Info->_Num_time_zones; ++_Idx) {
21112115 const string_view _Name{_Info->_Names[_Idx]};
21122116 if (_Info->_Links[_Idx] == nullptr) {
2113- _Time_zones.emplace_back(_Name);
2117+ _Time_zones.emplace_back(_Secret_time_zone_construct_tag{}, _Name);
21142118 } else {
21152119 const string_view _Target{_Info->_Links[_Idx]};
2116- _Time_zone_links.emplace_back(_Name, _Target);
2120+ _Time_zone_links.emplace_back(_Secret_time_zone_link_construct_tag{}, _Name, _Target);
21172121 }
21182122 }
21192123
@@ -2259,13 +2263,13 @@ namespace chrono {
22592263 vector<time_zone> _Zones;
22602264 _Zones.reserve(_Tzdb.zones.size());
22612265 for (const auto& _Tz : _Tzdb.zones) {
2262- _Zones.emplace_back(_Tz.name());
2266+ _Zones.emplace_back(_Secret_time_zone_construct_tag{}, _Tz.name());
22632267 }
22642268
22652269 vector<time_zone_link> _Links;
22662270 _Links.reserve(_Tzdb.links.size());
22672271 for (const auto& _Link : _Tzdb.links) {
2268- _Links.emplace_back(_Link.name(), _Link.target());
2272+ _Links.emplace_back(_Secret_time_zone_link_construct_tag{}, _Link.name(), _Link.target());
22692273 }
22702274
22712275 auto _Version = _Tzdb_update_version(_Tzdb.version, _Leap_sec.size());
@@ -3166,12 +3170,12 @@ namespace chrono {
31663170 }
31673171 }
31683172
3169- if (!_Val.has_value()) {
3170- _Val = _New;
3171- return true;
3172- } else {
3173- return _STD exchange(_Val, _New) == _New;
3173+ if (_Val.has_value()) {
3174+ return _STD exchange(*_Val, _New) == _New;
31743175 }
3176+
3177+ _Val = _New;
3178+ return true;
31753179 }
31763180
31773181 _NODISCARD static pair<int, int> _Decompose_year(const int _Year) {
@@ -3581,7 +3585,6 @@ namespace chrono {
35813585
35823586 template <class _DurationType>
35833587 _NODISCARD bool _Make_time_point(_DurationType& _Dur, _Leap_second_rep _Leap) {
3584-
35853588 const bool _Consistent{_Calculate_hour24() && _Calculate_year_fields() && _Calculate_ymd()};
35863589 if (!_Consistent || !_Apply_duration_fields<_Parse_tp_or_duration::_Time_point>(_Dur)) {
35873590 return false;
@@ -3609,7 +3612,7 @@ namespace chrono {
36093612 return false;
36103613 } else {
36113614 // It's possible that the parsed time doesn't exist because (a) _Seconds == 60 and there *isn't* a
3612- // leap second insertion or (b) _Seconds >= 59 and there *is* a leap second subtraction .
3615+ // leap second insertion or (b) _Seconds >= 59 and there *is* a leap second deletion .
36133616 const auto& _Tzdb{_CHRONO get_tzdb()};
36143617
36153618 const bool _Possible_insertion{_Second == 60};
@@ -3725,15 +3728,14 @@ namespace chrono {
37253728 }
37263729 }
37273730
3728- template <class _InIt>
3729- _NODISCARD _InIt _Parse_time_field(_InIt _First, ios_base& _Iosbase, ios_base::iostate& _State,
3730- const char _Flag, const char _Modifier, const unsigned int _Width,
3731- const unsigned int _Subsecond_precision) {
3732- using _CharT = _InIt::value_type;
3731+ template <class _CharT, class _Traits>
3732+ _NODISCARD istreambuf_iterator<_CharT, _Traits> _Parse_time_field(istreambuf_iterator<_CharT, _Traits> _First,
3733+ ios_base& _Iosbase, ios_base::iostate& _State, const char _Flag, const char _Modifier,
3734+ const unsigned int _Width, const unsigned int _Subsecond_precision) {
37333735
37343736 const auto& _Ctype_fac = _STD use_facet<ctype<_CharT>>(_Iosbase.getloc());
37353737 const auto& _Time_fac = _STD use_facet<time_get<_CharT>>(_Iosbase.getloc());
3736- constexpr _InIt _Last{};
3738+ constexpr istreambuf_iterator<_CharT, _Traits> _Last{};
37373739
37383740 int _Val{0};
37393741 switch (_Flag) {
@@ -4051,19 +4053,19 @@ namespace chrono {
40514053 return _First;
40524054 }
40534055
4054- template <class _InIt>
4055- _NODISCARD _InIt _Parse_time_field_restricted(_InIt _First, ios_base& _Iosbase, ios_base::iostate& _State,
4056+ template <class _CharT, class _Traits>
4057+ _NODISCARD istreambuf_iterator<_CharT, _Traits> _Parse_time_field_restricted(
4058+ istreambuf_iterator<_CharT, _Traits> _First, ios_base& _Iosbase, ios_base::iostate& _State,
40564059 const char* _Fmt, const unsigned int _Subsecond_precision = 0) {
4057- using _Ctype = ctype<typename _InIt::value_type>;
40584060 // Parses a restricted format string. It generally doesn't handle anything parsed outside of
40594061 // _Parse_time_field:
40604062 // (a) any whitespace (' ', %n, %t)
40614063 // (b) %% literal (other literals are parsed, however)
40624064 // (c) E or O modifiers
40634065 // (d) width parameter
40644066 // It also assumes a valid format string, specifically that '%' is always followed by a flag.
4065- const _Ctype & _Ctype_fac{_STD use_facet<_Ctype >(_Iosbase.getloc())};
4066- constexpr _InIt _Last{};
4067+ const auto & _Ctype_fac{_STD use_facet<ctype<_CharT> >(_Iosbase.getloc())};
4068+ constexpr istreambuf_iterator<_CharT, _Traits> _Last{};
40674069
40684070 while (*_Fmt != '\0' && (_State & ~ios_base::eofbit) == ios_base::goodbit) {
40694071 if (_First == _Last) {
@@ -4079,11 +4081,10 @@ namespace chrono {
40794081 return _First;
40804082 }
40814083
4082- template <class _InIt>
4083- _NODISCARD ios_base::iostate _Get_fixed(_InIt& _First, unsigned int _Width,
4084- const ctype<typename _InIt::value_type>& _Ctype_fac,
4085- const numpunct<typename _InIt::value_type>& _Numpunct_fac) {
4086- constexpr _InIt _Last{};
4084+ template <class _CharT, class _Traits>
4085+ _NODISCARD ios_base::iostate _Get_fixed(istreambuf_iterator<_CharT, _Traits>& _First, unsigned int _Width,
4086+ const ctype<_CharT>& _Ctype_fac, const numpunct<_CharT>& _Numpunct_fac) {
4087+ constexpr istreambuf_iterator<_CharT, _Traits> _Last{};
40874088
40884089 while (_First != _Last && _Ctype_fac.is(ctype_base::space, *_First) && _Width > 0) {
40894090 ++_First;
@@ -4132,10 +4133,10 @@ namespace chrono {
41324133 return _State;
41334134 }
41344135
4135- template <class _InIt >
4136- _NODISCARD ios_base::iostate _Get_int(
4137- _InIt& _First, unsigned int _Width, int & _Val, const ctype<typename _InIt::value_type >& _Ctype_fac) {
4138- constexpr _InIt _Last{};
4136+ template <class _CharT, class _Traits >
4137+ _NODISCARD ios_base::iostate _Get_int(istreambuf_iterator<_CharT, _Traits>& _First, unsigned int _Width,
4138+ int& _Val, const ctype<_CharT >& _Ctype_fac) {
4139+ constexpr istreambuf_iterator<_CharT, _Traits> _Last{};
41394140
41404141 while (_First != _Last && _Ctype_fac.is(ctype_base::space, *_First) && _Width > 0) {
41414142 ++_First;
@@ -4194,10 +4195,10 @@ namespace chrono {
41944195 return _State;
41954196 }
41964197
4197- template <class _InIt >
4198- _NODISCARD ios_base::iostate _Get_tz_offset(
4199- _InIt& _First, const ctype<typename _InIt::value_type >& _Ctype_fac, const bool _Is_modified, int& _Offset) {
4200- constexpr _InIt _Last{};
4198+ template <class _CharT, class _Traits >
4199+ _NODISCARD ios_base::iostate _Get_tz_offset(istreambuf_iterator<_CharT, _Traits>& _First,
4200+ const ctype<_CharT >& _Ctype_fac, const bool _Is_modified, int& _Offset) {
4201+ constexpr istreambuf_iterator<_CharT, _Traits> _Last{};
42014202 if (_First == _Last) {
42024203 return ios_base::eofbit;
42034204 }
@@ -4267,10 +4268,10 @@ namespace chrono {
42674268 return ios_base::goodbit;
42684269 }
42694270
4270- template <class _InIt >
4271+ template <class _CharT, class _Traits >
42714272 _NODISCARD ios_base::iostate _Get_tz_name(
4272- _InIt & _First, const ctype<typename _InIt::value_type >& _Ctype_fac, string& _Tz_name) {
4273- constexpr _InIt _Last{};
4273+ istreambuf_iterator<_CharT, _Traits> & _First, const ctype<_CharT >& _Ctype_fac, string& _Tz_name) {
4274+ constexpr istreambuf_iterator<_CharT, _Traits> _Last{};
42744275 _Tz_name.clear();
42754276 while (_First != _Last) {
42764277 const char _Ch{_Ctype_fac.narrow(*_First)};
@@ -4388,7 +4389,7 @@ namespace chrono {
43884389 }
43894390 }
43904391
4391- _CATCH_IO_(_Myis , _Istr)
4392+ _CATCH_IO_(ios_base , _Istr)
43924393 }
43934394
43944395 if (!_Is_complete()) {
@@ -4786,7 +4787,6 @@ public:
47864787 }
47874788
47884789 constexpr void _On_conversion_spec(char _Modifier, _CharT _Type) {
4789- // NOTE: same performance note from _Basic_format_specs also applies here
47904790 if (_Modifier != '\0' && _Modifier != 'E' && _Modifier != 'O') {
47914791 _Throw_format_error("Invalid modifier specification.");
47924792 }
@@ -4880,6 +4880,8 @@ _NODISCARD constexpr const _CharT* _Parse_chrono_format_specs(
48804880
48814881 // chrono-spec
48824882 while (_Begin != _End && *_Begin != '}') {
4883+ // Note that in this loop, ++_Begin is safe (and we don't need _Fmt_codec)
4884+ // because '%' isn't used as a non-lead-byte in any supported multibyte encoding.
48834885 if (*_Begin == '%') { // conversion-spec
48844886 if (++_Begin == _End) {
48854887 _Throw_format_error("Invalid format string - missing type after %");
@@ -5524,9 +5526,9 @@ namespace chrono {
55245526 _CharT _Fmt_str[4];
55255527 _Os << _STD put_time(&_Time, _Fmt_string({._Type = _Gregorian_type}, _Fmt_str));
55265528 return true;
5529+ } else {
5530+ return false;
55275531 }
5528-
5529- return false;
55305532 case 'r':
55315533 // put_time uses _Strftime in order to bypass reference-counting that locale uses. This function
55325534 // takes the locale information by pointer, but the pointer (from _Gettnames) returns a copy.
@@ -5544,16 +5546,21 @@ namespace chrono {
55445546 if constexpr (_Is_specialization_v<_Ty, duration>) {
55455547 _Os << _STD abs(_Duration_cast_underflow_to_zero<days>(_Val).count());
55465548 return true;
5549+ } else {
5550+ return false;
55475551 }
5548- return false;
55495552 case 'q':
55505553 if constexpr (_Is_specialization_v<_Ty, duration>) {
55515554 _Write_unit_suffix<typename _Ty::period>(_Os);
5555+ } else {
5556+ _STL_INTERNAL_CHECK(false);
55525557 }
55535558 return true;
55545559 case 'Q':
55555560 if constexpr (_Is_specialization_v<_Ty, duration>) {
55565561 _Os << _STD abs(_Val.count());
5562+ } else {
5563+ _STL_INTERNAL_CHECK(false);
55575564 }
55585565 return true;
55595566 case 'm': // Print months as a decimal, even if invalid.
@@ -5715,7 +5722,7 @@ namespace chrono {
57155722 case 'Y':
57165723 if constexpr (is_same_v<_Ty, year>) {
57175724 return _Val.ok();
5718- } else if constexpr (_Is_any_of_v <_Ty, year_month> || _Is_ymd) {
5725+ } else if constexpr (is_same_v <_Ty, year_month> || _Is_ymd) {
57195726 return _Val.year().ok();
57205727 }
57215728 break;
0 commit comments