https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114316
--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
For a debug mode _Safe_iterator pair __valid_range uses this overload:
template<typename _Iterator, typename _Sequence, typename _Category>
inline bool
__valid_range(const _Safe_iterator<_Iterator, _Sequence,
_Category>& __first,
const _Safe_iterator<_Iterator, _Sequence,
_Category>& __last)
{
typename _Distance_traits<_Iterator>::__type __dist;
return __first._M_valid_range(__last, __dist);
}
Which calls:
template<typename _Iterator, typename _Sequence, typename _Category>
bool
_Safe_iterator<_Iterator, _Sequence, _Category>::
_M_valid_range(const _Safe_iterator& __rhs,
std::pair<difference_type, _Distance_precision>& __dist,
bool __check_dereferenceable) const
{
if (_M_singular() || __rhs._M_singular() || !_M_can_compare(__rhs))
return false;
So it doesn't consider whether the range is empty.
For non-debug mode iterators we have:
template<typename _InputIterator>
_GLIBCXX_CONSTEXPR
inline bool
__valid_range_aux(_InputIterator __first, _InputIterator __last,
std::input_iterator_tag)
{
return __first == __last
|| (!__gnu_debug::__check_singular(__first)
&& !__gnu_debug::__check_singular(__last));
}
which gets it right.