Given:
struct Iter {
using value_type = int;
using difference_type = int;
using reference = int;
using pointer = int;
using iterator_category = int;
};
The following works fine with libstc++, but fails to compile against libc++ 5.0.0:
#include <iterator>
#include <type_traits>
static_assert(
std::is_same<
std::iterator_traits<Iter>::iterator_category,
Iter::iterator_category
>::value, "");
With the error:
error: no member named '
iterator_category
' in 'std::__1::iterator_traits<Iter>
'std::is_same<std::iterator_traits<Iter>::iterator_category, Iter::iterator_category>::value, "");
The static assertion succeeds if Iter::iterator_category
is one of the standard input categories, e.g. std::input_iterator_tag
.
IMHO it shouldn't fail, because the C++ draft states in [iterator.traits]#2:
If Iterator has valid ([temp.deduct]) member types
difference_type
,value_type
,pointer
,reference
, anditerator_category
,iterator_traits<Iterator>
shall have the following as publicly accessible members:using difference_type = typename Iterator::difference_type; using value_type = typename Iterator::value_type; using pointer = typename Iterator::pointer; using reference = typename Iterator::reference; using iterator_category = typename Iterator::iterator_category;
Otherwise,
iterator_traits<Iterator>
shall have no members by any of the above names.
Can anybody please explain whether this is an implementation bug, or why my expectations are wrong?
We also have, in [std.iterator.tags]:
int
isn't one of those tags, soiterator_traits<Iter>::iterator_category
can't give you backint
. I would suggest that having an invalid iterator category is simply violating the preconditions ofiterator_traits
- this doesn't necessarily mean that the library must fail, but it also doesn't mean that failure is a library bug.However, these preconditions aren't spelled out as explicitly in [iterators] as they are in other parts of the library section. So I'd be inclined to suggest that both libraries are correct, but libc++'s approach to not defining any member aliases in
iterator_traits<Iter>
is likely better.