diff options
author | Patrick Palka <ppalka@redhat.com> | 2025-02-28 09:39:57 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2025-02-28 09:39:57 -0500 |
commit | 4342c50ca84ae5448c0128c52120f4fe9005f203 (patch) | |
tree | b79ebb03ca9c264ccfd479005464af5570d0c1dc | |
parent | 7eb8ec1856f71b039d1c2235b1c941934fa28e22 (diff) | |
download | gcc-4342c50ca84ae5448c0128c52120f4fe9005f203.zip gcc-4342c50ca84ae5448c0128c52120f4fe9005f203.tar.gz gcc-4342c50ca84ae5448c0128c52120f4fe9005f203.tar.bz2 |
libstdc++: Fix constraint recursion in basic_const_iterator relops [PR112490]
Here for
using RCI = reverse_iterator<basic_const_iterator<vector<int>::iterator>>
static_assert(std::totally_ordered<RCI>);
we effectively need to check the requirement
requires (RCI x) { x RELOP x; } for each RELOP in {<, >, <=, >=}
which we expect to be straightforwardly satisfied by reverse_iterator's
namespace-scope relops. But due to ADL we find ourselves also
considering the basic_const_iterator relop friends, which before CWG
2369 would be quickly discarded since RCI clearly isn't convertible to
basic_const_iterator. After CWG 2369 though we must first check these
relops' constraints (with _It = vector<int>::iterator and _It2 = RCI),
which entails checking totally_ordered<RCI> recursively.
This patch fixes this by turning the problematic non-dependent function
parameters of type basic_const_iterator<_It> into dependent ones of
type basic_const_iterator<_It3> where _It3 is constrained to match _It.
Thus the basic_const_iterator relop friends now get quickly discarded
during deduction and before the constraint check if the second operand
isn't a specialization of basic_const_iterator (or derived from one)
like before CWG 2369.
PR libstdc++/112490
libstdc++-v3/ChangeLog:
* include/bits/stl_iterator.h (basic_const_iterator::operator<):
Replace non-dependent basic_const_iterator function parameter with
a dependent one of type basic_const_iterator<_It3> where _It3
matches _It.
(basic_const_iterator::operator>): Likewise.
(basic_const_iterator::operator<=): Likewise.
(basic_const_iterator::operator>=): Likewise.
* testsuite/24_iterators/const_iterator/112490.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
-rw-r--r-- | libstdc++-v3/include/bits/stl_iterator.h | 16 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc | 12 |
2 files changed, 20 insertions, 8 deletions
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 3e02534..33732b1 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -2881,30 +2881,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && three_way_comparable_with<_It, _It2> { return _M_current <=> __y; } - template<__detail::__not_a_const_iterator _It2> + template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3> friend constexpr bool - operator<(const _It2& __x, const basic_const_iterator& __y) + operator<(const _It2& __x, const basic_const_iterator<_It3>& __y) noexcept(noexcept(__x < __y._M_current)) requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> { return __x < __y._M_current; } - template<__detail::__not_a_const_iterator _It2> + template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3> friend constexpr bool - operator>(const _It2& __x, const basic_const_iterator& __y) + operator>(const _It2& __x, const basic_const_iterator<_It3>& __y) noexcept(noexcept(__x > __y._M_current)) requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> { return __x > __y._M_current; } - template<__detail::__not_a_const_iterator _It2> + template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3> friend constexpr bool - operator<=(const _It2& __x, const basic_const_iterator& __y) + operator<=(const _It2& __x, const basic_const_iterator<_It3>& __y) noexcept(noexcept(__x <= __y._M_current)) requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> { return __x <= __y._M_current; } - template<__detail::__not_a_const_iterator _It2> + template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3> friend constexpr bool - operator>=(const _It2& __x, const basic_const_iterator& __y) + operator>=(const _It2& __x, const basic_const_iterator<_It3>& __y) noexcept(noexcept(__x >= __y._M_current)) requires random_access_iterator<_It> && totally_ordered_with<_It, _It2> { return __x >= __y._M_current; } diff --git a/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc b/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc new file mode 100644 index 0000000..9bb1548 --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc @@ -0,0 +1,12 @@ +// { dg-do compile { target c++23 } } + +// PR libstdc++/112490 - infinite meta error in +// reverse_iterator<basic_const_iterator<vector<int>::iterator>> + +#include <iterator> +#include <vector> + +using I = std::vector<int>::iterator; +using CI = std::basic_const_iterator<I>; +using RCI = std::reverse_iterator<CI>; +static_assert(std::totally_ordered<RCI>); |