diff mbox series

libstdc++: Adjust std::span::iterator to be ADL-proof

Message ID 20240906205518.3288989-1-jwakely@redhat.com
State New
Headers show
Series libstdc++: Adjust std::span::iterator to be ADL-proof | expand

Commit Message

Jonathan Wakely Sept. 6, 2024, 8:50 p.m. UTC
This proposed patch means that span<T,E> is not an associated type of
span<T,E>::iterator, which means that we won't try to complete T when
doing ADL in the constraints for const_iterator. This makes it more
reliable to use std::span<IncompleteType>.

See https://github.com/llvm/llvm-project/issues/107215 for more info on
the problem and the constraint recursion that can happen.

Does this seem worthwhile?

It would be an ABI change to do something like this for other uses of
__normal_iterator, such as std::vector and std::string. But std::span is
a C++20 feature so still experimental. I think we should consider this
for other new uses of __normal_iterator too, e.g. in <stacktrace>.

-- >8 --

libstdc++-v3/ChangeLog:

	* include/std/span (span::__iter_tag): Declare nested type.
	(span::iterator): Use __iter_tag as second template argument.
---
 libstdc++-v3/include/std/span | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 00fc5279152..b7392a0500e 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -123,6 +123,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	using __is_compatible_ref
 	  = __is_array_convertible<_Type, remove_reference_t<_Ref>>;
 
+      // Nested type so that _Type is not an associated class of iterator.
+      struct __iter_tag;
+
     public:
       // member types
       using element_type           = _Type;
@@ -133,7 +136,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using const_pointer          = const _Type*;
       using reference              = element_type&;
       using const_reference        = const element_type&;
-      using iterator = __gnu_cxx::__normal_iterator<pointer, span>;
+      using iterator = __gnu_cxx::__normal_iterator<pointer, __iter_tag>;
       using reverse_iterator       = std::reverse_iterator<iterator>;
 #if __cplusplus > 202002L
       using const_iterator         = std::const_iterator<iterator>;