From fc0f803f3efb94744b04e80fb8ded6f0ddc71da5 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sun, 12 Feb 2023 17:57:44 -0800 Subject: [PATCH 1/2] LWG-3769 `basic_const_iterator::operator==` causes infinite constraint recursion We implemented an earlier version of the resolution, this is the final version approved by WG21. Fixes #3436 --- stl/inc/xutility | 82 +++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 7a66539e1c0..077097f2f30 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1932,72 +1932,74 @@ public: } template _Sent> - _NODISCARD constexpr bool operator==(const _Sent& _Se) const // per LWG-3769 + _NODISCARD constexpr bool operator==(const _Sent& _Se) const noexcept(noexcept(_Fake_copy_init(_Current == _Se))) /* strengthened */ { return _Current == _Se; } - _NODISCARD_FRIEND constexpr bool - operator<(const basic_const_iterator& _Left, const basic_const_iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current < _Right._Current))) // strengthened + _NODISCARD constexpr bool operator<(const basic_const_iterator& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current < _Right._Current))) // strengthened requires random_access_iterator<_Iter> { - return _Left._Current < _Right._Current; + return _Current < _Right._Current; } - _NODISCARD_FRIEND constexpr bool - operator>(const basic_const_iterator& _Left, const basic_const_iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current > _Right._Current))) // strengthened + _NODISCARD constexpr bool operator>(const basic_const_iterator& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current > _Right._Current))) // strengthened requires random_access_iterator<_Iter> { - return _Left._Current > _Right._Current; + return _Current > _Right._Current; } - _NODISCARD_FRIEND constexpr bool - operator<=(const basic_const_iterator& _Left, const basic_const_iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current <= _Right._Current))) // strengthened + _NODISCARD constexpr bool operator<=(const basic_const_iterator& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current <= _Right._Current))) // strengthened requires random_access_iterator<_Iter> { - return _Left._Current <= _Right._Current; + return _Current <= _Right._Current; } - _NODISCARD_FRIEND constexpr bool - operator>=(const basic_const_iterator& _Left, const basic_const_iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current >= _Right._Current))) // strengthened + _NODISCARD constexpr bool operator>=(const basic_const_iterator& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current >= _Right._Current))) // strengthened requires random_access_iterator<_Iter> { - return _Left._Current >= _Right._Current; + return _Current >= _Right._Current; } - _NODISCARD_FRIEND constexpr auto operator<=>(const basic_const_iterator& _Left, - const basic_const_iterator& _Right) noexcept(noexcept(_Left._Current <=> _Right._Current)) // strengthened + _NODISCARD constexpr auto operator<=>(const basic_const_iterator& _Right) const + noexcept(noexcept(_Current <=> _Right._Current)) // strengthened requires random_access_iterator<_Iter> && three_way_comparable<_Iter> { - return _Left._Current <=> _Right._Current; + return _Current <=> _Right._Current; } template <_Bci_order<_Iter> _Other> - _NODISCARD_FRIEND constexpr bool operator<(const basic_const_iterator& _Left, const _Other& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current < _Right))) /* strengthened */ { - return _Left._Current < _Right; + _NODISCARD constexpr bool operator<(const _Other& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current < _Right))) /* strengthened */ { + return _Current < _Right; } template <_Bci_order<_Iter> _Other> - _NODISCARD_FRIEND constexpr bool operator>(const basic_const_iterator& _Left, const _Other& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current > _Right))) /* strengthened */ { - return _Left._Current > _Right; + _NODISCARD constexpr bool operator>(const _Other& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current > _Right))) /* strengthened */ { + return _Current > _Right; } template <_Bci_order<_Iter> _Other> - _NODISCARD_FRIEND constexpr bool operator<=(const basic_const_iterator& _Left, const _Other& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current <= _Right))) /* strengthened */ { - return _Left._Current <= _Right; + _NODISCARD constexpr bool operator<=(const _Other& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current <= _Right))) /* strengthened */ { + return _Current <= _Right; } template <_Bci_order<_Iter> _Other> - _NODISCARD_FRIEND constexpr bool operator>=(const basic_const_iterator& _Left, const _Other& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current >= _Right))) /* strengthened */ { - return _Left._Current >= _Right; + _NODISCARD constexpr bool operator>=(const _Other& _Right) const + noexcept(noexcept(_Fake_copy_init(_Current >= _Right))) /* strengthened */ { + return _Current >= _Right; + } + + template <_Bci_order_3way<_Iter> _Other> + _NODISCARD constexpr auto operator<=>(const _Other& _Right) const + noexcept(noexcept(_Current <=> _Right)) /* strengthened */ { + return _Current <=> _Right; } template <_Not_bci_order<_Iter> _Other> @@ -2024,12 +2026,6 @@ public: return _Left >= _Right._Current; } - template <_Bci_order_3way<_Iter> _Other> - _NODISCARD_FRIEND constexpr auto operator<=>(const basic_const_iterator& _Left, const _Other& _Right) noexcept( - noexcept(_Left._Current <=> _Right)) /* strengthened */ { - return _Left._Current <=> _Right; - } - _NODISCARD_FRIEND constexpr basic_const_iterator operator+(const basic_const_iterator& _It, const difference_type _Off) noexcept(noexcept(basic_const_iterator{_It._Current + _Off})) // strengthened requires random_access_iterator<_Iter> @@ -2052,7 +2048,7 @@ public: } template _Sent> - _NODISCARD constexpr difference_type operator-(const _Sent& _Se) const // per LWG-3769 + _NODISCARD constexpr difference_type operator-(const _Sent& _Se) const noexcept(noexcept(_Current - _Se)) /* strengthened */ { return _Current - _Se; } @@ -2060,7 +2056,7 @@ public: template <_Not_a_const_iterator _Sent> requires sized_sentinel_for<_Sent, _Iter> _NODISCARD_FRIEND constexpr difference_type operator-(const _Sent& _Se, const basic_const_iterator& _It) noexcept( - noexcept(_Se - _It._Current)) /* strengthened */ { // per LWG-3769 + noexcept(_Se - _It._Current)) /* strengthened */ { return _Se - _It._Current; } }; @@ -3135,15 +3131,15 @@ namespace ranges { template _Se> requires (!sized_sentinel_for<_Se, _It>) _NODISCARD constexpr iter_difference_t<_It> operator()(_It _First, _Se _Last) const - noexcept(noexcept(_Distance_unchecked(_Get_unwrapped(_STD move(_First)), - _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { // Per LWG-3664 + noexcept(noexcept(_Distance_unchecked( + _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { _Adl_verify_range(_First, _Last); return _Distance_unchecked(_Unwrap_iter<_Se>(_STD move(_First)), _Unwrap_sent<_It>(_STD move(_Last))); } template > _Se> _NODISCARD constexpr iter_difference_t> operator()(_It&& _First, const _Se _Last) const - noexcept(noexcept(_Last - static_cast&>(_First))) /* strengthened */ { // Per LWG-3664 + noexcept(noexcept(_Last - static_cast&>(_First))) /* strengthened */ { return _Last - static_cast&>(_First); } From b6052a85d7f65f2ee0b27b46637b57e737ac459e Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sun, 12 Feb 2023 20:53:29 -0800 Subject: [PATCH 2/2] Revert leakage from another PR --- stl/inc/xutility | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 077097f2f30..6077729f46a 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3131,15 +3131,15 @@ namespace ranges { template _Se> requires (!sized_sentinel_for<_Se, _It>) _NODISCARD constexpr iter_difference_t<_It> operator()(_It _First, _Se _Last) const - noexcept(noexcept(_Distance_unchecked( - _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { + noexcept(noexcept(_Distance_unchecked(_Get_unwrapped(_STD move(_First)), + _Get_unwrapped(_STD move(_Last))))) /* strengthened */ { // Per LWG-3664 _Adl_verify_range(_First, _Last); return _Distance_unchecked(_Unwrap_iter<_Se>(_STD move(_First)), _Unwrap_sent<_It>(_STD move(_Last))); } template > _Se> _NODISCARD constexpr iter_difference_t> operator()(_It&& _First, const _Se _Last) const - noexcept(noexcept(_Last - static_cast&>(_First))) /* strengthened */ { + noexcept(noexcept(_Last - static_cast&>(_First))) /* strengthened */ { // Per LWG-3664 return _Last - static_cast&>(_First); }