Open ericniebler opened 6 years ago
I don't think this is wrong, per se. If the iterator fails to meet the requirements of cpp17-input-iterator (and doesn't specify the nested iterator type aliases and doesn't specialize std::iterator_traits
) then it clearly cannot have std::input_iterator_tag
as its iterator_category
.
The only slightly surprising bit is that a nested ::iterator_category
is not used if any of the other nested type aliases are absent (with the exception of ::pointer
which is optional). This will happen when the user writes a C++20 input iterator sans a self-comparing operator==
and tries to pass it to a legacy STL algorithm.
We could help users along a little bit by requiring output iterators to either specify no iterator_category
, or else to require it to be derived from std::output_iterator_tag
. That will cause the primary std::iterator_traits
struct to be empty should the user write a (C++20) input iterator sans a self-comparing operator==
, rending the users iterator not-a-cpp17-iterator. (It will, however, still be a valid C++20 iterator and usable with the algorithms in std::ranges
.)
Change [iterator.traits]/p3.3 as follows:
Otherwise, if
I
satisfies the exposition-only concept cpp17-iterator and either (a)I::iterator_category
is valid and denotesstd::output_iterator_tag
or a type publicly and unambiguously derived fromstd::output_iterator_tag
, or (b) there is no typeI::iterator_category
, theniterator_traits<I>
has the following publicly accessible members:
@CaseyCarter for your review.
Working through the specification for the primary
std::iterator_traits
template, an input iterator that is not EqualityComparable is given aniterator_category
ofstd::output_iterator_tag
. That's a bit odd. Rethink this.