diff --git a/stl/inc/iterator b/stl/inc/iterator index 95baaec830..2aeb23824c 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -804,23 +804,23 @@ public: }; // clang-format off +template +concept _Use_postfix_proxy = !requires(_Iter& __it) { { *__it++ } -> _Can_reference; } + && indirectly_readable<_Iter> // Per LWG-3601 + && constructible_from, iter_reference_t<_Iter>> + && move_constructible>; + template _Se> requires (!same_as<_Iter, _Se> && copyable<_Iter>) class common_iterator { // clang-format on private: - class _Proxy { - private: + struct _Proxy_base { iter_value_t<_Iter> _Keep; - public: - explicit _Proxy(iter_reference_t<_Iter>&& _Right) noexcept( - is_nothrow_move_constructible_v>) // strengthened - : _Keep(_STD move(_Right)) {} - - _NODISCARD const iter_value_t<_Iter>* operator->() const noexcept /* strengthened */ { - return _STD addressof(_Keep); - } + explicit _Proxy_base(iter_reference_t<_Iter>&& _Right) noexcept( + is_nothrow_constructible_v, iter_reference_t<_Iter>>) // strengthened + : _Keep(_STD forward>(_Right)) {} }; public: @@ -874,20 +874,31 @@ public: // clang-format off _NODISCARD decltype(auto) operator->() const requires indirectly_readable - && (_Has_member_arrow<_Iter> || is_reference_v> + && (_Has_member_arrow || is_reference_v> || constructible_from, iter_reference_t<_Iter>>) { // clang-format on #if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Val._Contains == _Variantish_state::_Holds_iter, "common_iterator can only be dereferenced if it holds an iterator"); #endif // _ITERATOR_DEBUG_LEVEL != 0 - if constexpr (is_pointer_v<_Iter> || _Has_member_arrow<_Iter>) { + if constexpr (_Has_member_arrow || is_pointer_v<_Iter>) { return (_Val._Iterator); // NB: () are necessary for decltype(auto) } else if constexpr (is_reference_v>) { auto&& _Tmp = *_Val._Iterator; return _STD addressof(_Tmp); } else { - return _Proxy{*_Val._Iterator}; + class _Arrow_proxy : private _Proxy_base { + public: + friend common_iterator; + + using _Proxy_base::_Proxy_base; + + _NODISCARD const iter_value_t<_Iter>* operator->() const noexcept /* strengthened */ { + return _STD addressof(this->_Keep); + } + }; + + return _Arrow_proxy{*_Val._Iterator}; } } @@ -909,6 +920,21 @@ public: common_iterator _Tmp = *this; ++_Val._Iterator; return _Tmp; + } else if constexpr (_Use_postfix_proxy<_Iter>) { + class _Postfix_proxy : private _Proxy_base { + public: + friend common_iterator; + + using _Proxy_base::_Proxy_base; + + _NODISCARD const iter_value_t<_Iter>& operator*() const noexcept /* strengthened */ { + return this->_Keep; + } + }; + + _Postfix_proxy _Tmp{*_Val._Iterator}; + ++_Val._Iterator; + return _Tmp; } else { return _Val._Iterator++; }