[PATCH] libstdc++: Fix constraint recursion in std:indirect's operator== [PR124890]

Patrick Palka ppalka@redhat.com
Fri Apr 17 17:02:52 GMT 2026


On Fri, 17 Apr 2026, Jonathan Wakely wrote:

> On Fri, 17 Apr 2026 at 16:40, Patrick Palka <ppalka@redhat.com> wrote:
> >
> > Tested on x86_64-pc-linux-gnu, does this look OK for trunk?
> 
> OK, thanks.
> 
> >
> > We can also just implement the Mandates as a static_assert as pointed
> > out by Lénárd.  Otherwise, I prefer this approach rather than the
> > forwarding reference approach since it's cleaner and we use this approach
> > in other parts of the library with no complaints so far.
> >
> > -- >8 --
> >
> > Like in r16-559 for std::expected, std::indirect's operator== is also
> > prone to constraint recursion due to CWG 2369.  This patch works around
> > the recursion in a similar manner.
> >
> >         PR libstdc++/124890
> >         PR libstdc++/119714
> >         PR libstdc++/112490
> >
> > libstdc++-v3/ChangeLog:
> >
> >         * include/bits/indirect.h (indirect::operator==): Replace
> >         non-dependent std::indirect function parameter with a
> >         dependent one of type indirect<_Tp2> where _Tp2 matches _Tp.
> >         * testsuite/std/memory/indirect/124890.cc: New test.
> > ---
> >  libstdc++-v3/include/bits/indirect.h                 | 4 ++--
> >  libstdc++-v3/testsuite/std/memory/indirect/124890.cc | 9 +++++++++
> >  2 files changed, 11 insertions(+), 2 deletions(-)
> >  create mode 100644 libstdc++-v3/testsuite/std/memory/indirect/124890.cc
> >
> > diff --git a/libstdc++-v3/include/bits/indirect.h b/libstdc++-v3/include/bits/indirect.h
> > index 2df46cc39a21..e1f7d1968b56 100644
> > --- a/libstdc++-v3/include/bits/indirect.h
> > +++ b/libstdc++-v3/include/bits/indirect.h
> > @@ -344,11 +344,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >             return __lhs.__get() == __rhs.__get();
> >         }
> >
> > -      template<typename _Up>
> > +      template<same_as<_Tp> _Tp2, typename _Up>
> >         requires (!__is_indirect<_Up>) // See PR c++/99599
> >           && requires (const _Tp& __t, const _Up& __u) { __t == __u; }
> >         friend constexpr bool
> > -       operator==(const indirect& __lhs, const _Up& __rhs)
> > +       operator==(const indirect<_Tp2>& __lhs, const _Up& __rhs)

Oops, forgot to pass the _Alloc parameter here.  Here's what I ended up
pushing:

-- >8 --

Subject: [PATCH] libstdc++: Fix constraint recursion in std::indirect's
 operator== [PR124890]

Like in r16-559 for std::expected, std::indirect's operator== is also
prone to constraint recursion due to CWG 2369, for the Mandates that we
implement as an associated constraint.  This patch works around the
recursion in a similar manner as done for std::expected (and
std::basic_const_iterator).

	PR libstdc++/124890
	PR libstdc++/119714
	PR libstdc++/112490

libstdc++-v3/ChangeLog:

	* include/bits/indirect.h (indirect::operator==): Replace
	non-dependent std::indirect function parameter with a
	dependent one of type indirect<_Vp> where _Vp matches _Tp.
	* testsuite/std/memory/indirect/124890.cc: New test.

Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
---
 libstdc++-v3/include/bits/indirect.h                 | 4 ++--
 libstdc++-v3/testsuite/std/memory/indirect/124890.cc | 9 +++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/std/memory/indirect/124890.cc

diff --git a/libstdc++-v3/include/bits/indirect.h b/libstdc++-v3/include/bits/indirect.h
index 2df46cc39a21..6490a77a5079 100644
--- a/libstdc++-v3/include/bits/indirect.h
+++ b/libstdc++-v3/include/bits/indirect.h
@@ -344,11 +344,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    return __lhs.__get() == __rhs.__get();
 	}
 
-      template<typename _Up>
+      template<typename _Up, same_as<_Tp> _Vp>
 	requires (!__is_indirect<_Up>) // See PR c++/99599
 	  && requires (const _Tp& __t, const _Up& __u) { __t == __u; }
 	friend constexpr bool
-	operator==(const indirect& __lhs, const _Up& __rhs)
+	operator==(const indirect<_Vp, _Alloc>& __lhs, const _Up& __rhs)
 	noexcept(noexcept(*__lhs == __rhs))
 	{
 	  if (!__lhs._M_objp)
diff --git a/libstdc++-v3/testsuite/std/memory/indirect/124890.cc b/libstdc++-v3/testsuite/std/memory/indirect/124890.cc
new file mode 100644
index 000000000000..ce44256f2244
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/memory/indirect/124890.cc
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++26 } }
+
+// PR libstdc++/124890 - Circular constraint in std::indirect::operator==
+
+#include <memory>
+#include <vector>
+
+using I = std::vector<std::indirect<int>>::iterator;
+static_assert(std::totally_ordered<I>);
-- 
2.54.0.rc1.54.g60f07c4f5c



More information about the Libstdc++ mailing list