Andrey Semashev wrote:
I can reproduce it locally with clang 3.4. Shows only with -std=c++11 -stdlib=libc++. Trying to dig further.
Ah. Sneaky hobbits. Conforming extension my posterior. :-) (Actually, it _is_ a conforming extension, by a strict reading of the standard. Still, I'd have preferred a little less cleverness.) template <class _Tp> struct __has_iterator_category { private: struct __two {char __lx; char __lxx;}; template <class _Up> static __two __test(...); template <class _Up> static char __test(typename _Up::iterator_category* = 0); public: static const bool value = sizeof(__test<_Tp>(0)) == 1; }; template <class _Iter, bool> struct __iterator_traits_impl {}; template <class _Iter> struct __iterator_traits_impl<_Iter, true> { typedef typename _Iter::difference_type difference_type; typedef typename _Iter::value_type value_type; typedef typename _Iter::pointer pointer; typedef typename _Iter::reference reference; typedef typename _Iter::iterator_category iterator_category; }; template <class _Iter, bool> struct __iterator_traits {}; template <class _Iter> struct __iterator_traits<_Iter, true> : __iterator_traits_impl < _Iter, is_convertible<typename _Iter::iterator_category, input_iterator_tag>::value || is_convertible<typename _Iter::iterator_category, output_iterator_tag>::value > {}; // iterator_traits<Iterator> will only have the nested types if Iterator::iterator_category // exists. Else iterator_traits<Iterator> will be an empty class. This is a // conforming extension which allows some programs to compile and behave as // the client expects instead of failing at compile time. template <class _Iter> struct _LIBCPP_TYPE_VIS_ONLY iterator_traits : __iterator_traits<_Iter, __has_iterator_category<_Iter>::value> {};