https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91054

            Bug ID: 91054
           Summary: replace __gnu_cxx::__normal_iterator<T*, C> by
                    C::iterator in diagnostics
           Product: gcc
           Version: 9.1.0
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: enhancement
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
  Target Milestone: ---

Libstdc++ uses the __gnu_cxx::__normal_iterator class type for std::vector and
std::basic_string iterators, but it obfuscates diagnostics.

It would be much nicer to automatically replace the type's real name with the
public typedef that users are familiar with.

For this invalid program:

#include <vector>
int main()
{
  std::vector<int> v;
  auto iter1 = v.begin();
  auto iter2 = v.crbegin();
  std::distance(iter1, iter2);
}


G++ prints:

iter.cc: In function 'int main()':
iter.cc:7:29: error: no matching function for call to
'distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&,
std::reverse_iterator<__gnu_cxx::__normal_iterator<const int*, std::vector<int>
> >&)'
    7 |   std::distance(iter1, iter2);
      |                             ^
In file included from
/home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_algobase.h:66,
                 from /home/jwakely/gcc/10/include/c++/10.0.0/vector:60,
                 from iter.cc:1:
/home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_iterator_base_funcs.h:138:5:
note: candidate: 'template<class _InputIterator> typename
std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator,
_InputIterator)'
  138 |     distance(_InputIterator __first, _InputIterator __last)
      |     ^~~~~~~~
/home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_iterator_base_funcs.h:138:5:
note:   template argument deduction/substitution failed:
iter.cc:7:29: note:   deduced conflicting types for parameter '_InputIterator'
('__gnu_cxx::__normal_iterator<int*, std::vector<int> >' and
'std::reverse_iterator<__gnu_cxx::__normal_iterator<const int*,
std::vector<int> > >')
    7 |   std::distance(iter1, iter2);
      |                             ^


I think this is easier to read as:

iter.cc: In function 'int main()':
iter.cc:7:29: error: no matching function for call to
'distance(std::vector<int>::iterator&,
std::reverse_iterator<std::vector<int>::const_iterator >&)'
    7 |   std::distance(iter1, iter2);
      |                             ^
In file included from
/home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_algobase.h:66,
                 from /home/jwakely/gcc/10/include/c++/10.0.0/vector:60,
                 from iter.cc:1:
/home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_iterator_base_funcs.h:138:5:
note: candidate: 'template<class _InputIterator> typename
std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator,
_InputIterator)'
  138 |     distance(_InputIterator __first, _InputIterator __last)
      |     ^~~~~~~~
/home/jwakely/gcc/10/include/c++/10.0.0/bits/stl_iterator_base_funcs.h:138:5:
note:   template argument deduction/substitution failed:
iter.cc:7:29: note:   deduced conflicting types for parameter '_InputIterator'
('std::vector<int>::iterator' and
'std::reverse_iterator<std::vector<int>::const_iterator >')
    7 |   std::distance(iter1, iter2);
      |                             ^


This is the result of two simplifications:
Replace __gnu_cxx::__normal_iterator<const T*, C> with C::const_iterator
and replace __gnu_cxx::__normal_iterator<T*, C> with C::iterator.

As a further step we could consider replacing
std::reverse_iterator<std::C::iterator> with std::C::reverse_iterator, and
replacing std::reverse_iterator<std::C::const_iterator> with
std::C::const_reverse_iterator. That's more questionable, because it's possible
that the user code actually does spell out
std::reverse_iterator<std::C::iterator> rather than using the
C::reverse_iterator typedef.

For the __gnu_cxx::__normal_iterator case users should never be referring to
that type, they should only use the public and portable C::iterator and
C::const_iterator typedefs.

Reply via email to