@@ -886,7 +886,7 @@ public:
886886 constexpr common_iterator(const common_iterator<_OIter, _OSe>& _Right)
887887 noexcept(is_nothrow_constructible_v<_Iter, const _OIter&>
888888 && is_nothrow_constructible_v<_Se, const _OSe&>) // strengthened
889- : _Val{_Right._Get_val ()} {}
889+ : _Val{_Right._Get_val_for_hardened_construction ()} {}
890890
891891 template <class _OIter, class _OSe>
892892 requires convertible_to<const _OIter&, _Iter> && convertible_to<const _OSe&, _Se>
@@ -895,25 +895,30 @@ public:
895895 noexcept(is_nothrow_constructible_v<_Iter, const _OIter&> && is_nothrow_constructible_v<_Se, const _OSe&>
896896 && is_nothrow_assignable_v<_Iter&, const _OIter&>
897897 && is_nothrow_assignable_v<_Se&, const _OSe&>) /* strengthened */ {
898- _Val = _Right._Get_val();
898+ auto& _Right_val = _Right._Get_val();
899+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
900+ _STL_VERIFY(_Right_val._Contains != _Variantish_state::_Nothing,
901+ "common_iterator can only be assigned from if it holds a value");
902+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
903+ _Val = _Right_val;
899904 return *this;
900905 }
901906
902907 _NODISCARD constexpr decltype(auto) operator*() {
903- #if _ITERATOR_DEBUG_LEVEL != 0
908+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
904909 _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
905910 "common_iterator can only be dereferenced if it holds an iterator");
906- #endif // _ITERATOR_DEBUG_LEVEL != 0
911+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
907912 return *_Val._Get_first();
908913 }
909914
910915 _NODISCARD constexpr decltype(auto) operator*() const
911916 requires _Dereferenceable<const _Iter>
912917 {
913- #if _ITERATOR_DEBUG_LEVEL != 0
918+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
914919 _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
915920 "common_iterator can only be dereferenced if it holds an iterator");
916- #endif // _ITERATOR_DEBUG_LEVEL != 0
921+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
917922 return *_Val._Get_first();
918923 }
919924
@@ -922,10 +927,10 @@ public:
922927 && (_Has_member_arrow<const _Iter&> || is_reference_v<iter_reference_t<_Iter>>
923928 || constructible_from<iter_value_t<_Iter>, iter_reference_t<_Iter>>)
924929 {
925- #if _ITERATOR_DEBUG_LEVEL != 0
930+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
926931 _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
927932 "common_iterator can only be dereferenced if it holds an iterator");
928- #endif // _ITERATOR_DEBUG_LEVEL != 0
933+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
929934 if constexpr (_Has_member_arrow<const _Iter&> || is_pointer_v<_Iter>) {
930935 return _Val._Get_first();
931936 } else if constexpr (is_reference_v<iter_reference_t<_Iter>>) {
@@ -948,19 +953,19 @@ public:
948953 }
949954
950955 constexpr common_iterator& operator++() {
951- #if _ITERATOR_DEBUG_LEVEL != 0
956+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
952957 _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
953958 "common_iterator can only be incremented if it holds an iterator");
954- #endif // _ITERATOR_DEBUG_LEVEL != 0
959+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
955960 ++_Val._Get_first();
956961 return *this;
957962 }
958963
959964 constexpr decltype(auto) operator++(int) {
960- #if _ITERATOR_DEBUG_LEVEL != 0
965+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
961966 _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_first,
962967 "common_iterator can only be incremented if it holds an iterator");
963- #endif // _ITERATOR_DEBUG_LEVEL != 0
968+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
964969 if constexpr (forward_iterator<_Iter>) {
965970 common_iterator _Tmp = *this;
966971 ++_Val._Get_first();
@@ -990,11 +995,11 @@ public:
990995 _NODISCARD friend constexpr bool operator==(
991996 const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
992997 auto& _Right_val = _Right._Get_val();
993- #if _ITERATOR_DEBUG_LEVEL != 0
998+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
994999 _STL_VERIFY(
9951000 _Left._Val._Contains != _Variantish_state::_Nothing && _Right_val._Contains != _Variantish_state::_Nothing,
9961001 "common_iterators can only be compared if both hold a value");
997- #endif // _ITERATOR_DEBUG_LEVEL != 0
1002+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
9981003
9991004 if (_Left._Val._Contains == _Variantish_state::_Holds_first) {
10001005 if (_Right_val._Contains == _Variantish_state::_Holds_first) {
@@ -1020,11 +1025,11 @@ public:
10201025 _NODISCARD friend constexpr iter_difference_t<_OIter> operator-(
10211026 const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right) {
10221027 auto& _Right_val = _Right._Get_val();
1023- #if _ITERATOR_DEBUG_LEVEL != 0
1028+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10241029 _STL_VERIFY(
10251030 _Left._Val._Contains != _Variantish_state::_Nothing && _Right_val._Contains != _Variantish_state::_Nothing,
10261031 "Cannot take difference of valueless common_iterators");
1027- #endif // _ITERATOR_DEBUG_LEVEL != 0
1032+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10281033
10291034 if (_Left._Val._Contains == _Variantish_state::_Holds_first) {
10301035 if (_Right_val._Contains == _Variantish_state::_Holds_first) {
@@ -1045,22 +1050,22 @@ public:
10451050 noexcept(noexcept(_RANGES iter_move(_Right._Val._Get_first())))
10461051 requires input_iterator<_Iter>
10471052 {
1048- #if _ITERATOR_DEBUG_LEVEL != 0
1053+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10491054 _STL_VERIFY(_Right._Val._Contains == _Variantish_state::_Holds_first,
10501055 "can only iter_move from common_iterator if it holds an iterator");
1051- #endif // _ITERATOR_DEBUG_LEVEL != 0
1056+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10521057 return _RANGES iter_move(_Right._Val._Get_first());
10531058 }
10541059
10551060 template <indirectly_swappable<_Iter> _OIter, class _OSe>
10561061 friend constexpr void iter_swap(const common_iterator& _Left, const common_iterator<_OIter, _OSe>& _Right)
10571062 noexcept(noexcept(_RANGES iter_swap(_Left._Val._Get_first(), _Right._Get_val()._Get_first()))) {
10581063 auto& _Right_val = _Right._Get_val();
1059- #if _ITERATOR_DEBUG_LEVEL != 0
1064+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10601065 _STL_VERIFY(_Left._Val._Contains == _Variantish_state::_Holds_first
10611066 && _Right_val._Contains == _Variantish_state::_Holds_first,
10621067 "can only iter_swap common_iterators if both hold iterators");
1063- #endif // _ITERATOR_DEBUG_LEVEL != 0
1068+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
10641069 return _RANGES iter_swap(_Left._Val._Get_first(), _Right_val._Get_first());
10651070 }
10661071
@@ -1071,6 +1076,14 @@ public:
10711076 return _Val;
10721077 }
10731078
1079+ _NODISCARD constexpr const _Variantish<_Iter, _Se>& _Get_val_for_hardened_construction() const noexcept {
1080+ #if _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1081+ _STL_VERIFY(_Val._Contains != _Variantish_state::_Nothing,
1082+ "common_iterator can only be constructed from if it holds a value");
1083+ #endif // _MSVC_STL_HARDENING_COMMON_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1084+ return _Val;
1085+ }
1086+
10741087private:
10751088 _Variantish<_Iter, _Se> _Val;
10761089};
@@ -1153,9 +1166,9 @@ public:
11531166 constexpr counted_iterator(_Iter _Right, const iter_difference_t<_Iter> _Diff)
11541167 noexcept(is_nothrow_move_constructible_v<_Iter>) // strengthened
11551168 : _Current(_STD move(_Right)), _Length(_Diff) {
1156- #if _ITERATOR_DEBUG_LEVEL != 0
1169+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11571170 _STL_VERIFY(_Diff >= 0, "counted_iterator requires non-negative length n");
1158- #endif // _ITERATOR_DEBUG_LEVEL != 0
1171+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11591172 }
11601173
11611174 template <class _Other>
@@ -1188,18 +1201,18 @@ public:
11881201
11891202 // [counted.iter.elem]
11901203 _NODISCARD constexpr decltype(auto) operator*() noexcept(noexcept(*_Current)) /* strengthened */ {
1191- #if _ITERATOR_DEBUG_LEVEL != 0
1204+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11921205 _STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
1193- #endif // _ITERATOR_DEBUG_LEVEL != 0
1206+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
11941207 return *_Current;
11951208 }
11961209
11971210 _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Current)) /* strengthened */
11981211 requires _Dereferenceable<const _Iter>
11991212 {
1200- #if _ITERATOR_DEBUG_LEVEL != 0
1213+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12011214 _STL_VERIFY(_Length > 0, "counted_iterator dereference beyond end of range");
1202- #endif // _ITERATOR_DEBUG_LEVEL != 0
1215+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12031216 return *_Current;
12041217 }
12051218
@@ -1212,26 +1225,26 @@ public:
12121225 _NODISCARD constexpr decltype(auto) operator[](const iter_difference_t<_Iter> _Diff) const
12131226 requires random_access_iterator<_Iter>
12141227 {
1215- #if _ITERATOR_DEBUG_LEVEL != 0
1228+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12161229 _STL_VERIFY(_Diff < _Length, "counted_iterator index out of range");
1217- #endif // _ITERATOR_DEBUG_LEVEL != 0
1230+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12181231 return _Current[_Diff];
12191232 }
12201233
12211234 // [counted.iter.nav]
12221235 constexpr counted_iterator& operator++() {
1223- #if _ITERATOR_DEBUG_LEVEL != 0
1236+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12241237 _STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
1225- #endif // _ITERATOR_DEBUG_LEVEL != 0
1238+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12261239 ++_Current;
12271240 --_Length;
12281241 return *this;
12291242 }
12301243
12311244 constexpr decltype(auto) operator++(int) {
1232- #if _ITERATOR_DEBUG_LEVEL != 0
1245+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12331246 _STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
1234- #endif // _ITERATOR_DEBUG_LEVEL != 0
1247+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12351248 --_Length;
12361249 _TRY_BEGIN
12371250 return _Current++;
@@ -1246,9 +1259,9 @@ public:
12461259 constexpr counted_iterator operator++(int)
12471260 requires forward_iterator<_Iter>
12481261 {
1249- #if _ITERATOR_DEBUG_LEVEL != 0
1262+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12501263 _STL_VERIFY(_Length > 0, "counted_iterator increment beyond end of range");
1251- #endif // _ITERATOR_DEBUG_LEVEL != 0
1264+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12521265 counted_iterator _Tmp = *this;
12531266 ++_Current;
12541267 --_Length;
@@ -1288,9 +1301,9 @@ public:
12881301 constexpr counted_iterator& operator+=(const iter_difference_t<_Iter> _Diff)
12891302 requires random_access_iterator<_Iter>
12901303 {
1291- #if _ITERATOR_DEBUG_LEVEL != 0
1304+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12921305 _STL_VERIFY(_Diff <= _Length, "counted_iterator seek beyond end of range");
1293- #endif // _ITERATOR_DEBUG_LEVEL != 0
1306+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
12941307 _Current += _Diff;
12951308 _Length -= _Diff;
12961309 return *this;
@@ -1324,9 +1337,9 @@ public:
13241337 constexpr counted_iterator& operator-=(const iter_difference_t<_Iter> _Diff)
13251338 requires random_access_iterator<_Iter>
13261339 {
1327- #if _ITERATOR_DEBUG_LEVEL != 0
1340+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13281341 _STL_VERIFY(-_Diff <= _Length, "counted_iterator decrement beyond end of range");
1329- #endif // _ITERATOR_DEBUG_LEVEL != 0
1342+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13301343 _Current -= _Diff;
13311344 _Length += _Diff;
13321345 return *this;
@@ -1360,12 +1373,18 @@ public:
13601373 noexcept(noexcept(_RANGES iter_move(_Right._Current)))
13611374 requires input_iterator<_Iter>
13621375 {
1376+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1377+ _STL_VERIFY(_Right._Length > 0, "iter_move on a counted_iterator beyond end of range");
1378+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13631379 return _RANGES iter_move(_Right._Current);
13641380 }
13651381
13661382 template <indirectly_swappable<_Iter> _Other>
13671383 friend constexpr void iter_swap(const counted_iterator& _Left, const counted_iterator<_Other>& _Right)
13681384 noexcept(noexcept(_RANGES iter_swap(_Left._Current, _Right.base()))) {
1385+ #if _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
1386+ _STL_VERIFY(_Left._Length > 0 && _Right.count() > 0, "iter_swap on a counted_iterator beyond end of range");
1387+ #endif // _MSVC_STL_HARDENING_COUNTED_ITERATOR || _ITERATOR_DEBUG_LEVEL != 0
13691388 _RANGES iter_swap(_Left._Current, _Right.base());
13701389 }
13711390
0 commit comments