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 --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>; -- 2.46.0