diff options
3 files changed, 141 insertions, 1 deletions
diff --git a/libcxx/include/iterator b/libcxx/include/iterator index aed0525dbf8..bda177e11e6 100644 --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -438,6 +438,23 @@ struct _LIBCPP_TEMPLATE_VIS bidirectional_iterator_tag : public forward_iterator struct _LIBCPP_TEMPLATE_VIS random_access_iterator_tag : public bidirectional_iterator_tag {}; template <class _Tp> +struct __has_iterator_typedefs +{ +private: + struct __two {char __lx; char __lxx;}; + template <class _Up> static __two __test(...); + template <class _Up> static char __test(typename std::__void_t<typename _Up::iterator_category>::type* = 0, + typename std::__void_t<typename _Up::difference_type>::type* = 0, + typename std::__void_t<typename _Up::value_type>::type* = 0, + typename std::__void_t<typename _Up::reference>::type* = 0, + typename std::__void_t<typename _Up::pointer>::type* = 0 + ); +public: + static const bool value = sizeof(__test<_Tp>(0,0,0,0,0)) == 1; +}; + + +template <class _Tp> struct __has_iterator_category { private: @@ -479,7 +496,7 @@ struct __iterator_traits<_Iter, true> template <class _Iter> struct _LIBCPP_TEMPLATE_VIS iterator_traits - : __iterator_traits<_Iter, __has_iterator_category<_Iter>::value> {}; + : __iterator_traits<_Iter, __has_iterator_typedefs<_Iter>::value> {}; template<class _Tp> struct _LIBCPP_TEMPLATE_VIS iterator_traits<_Tp*> diff --git a/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp b/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp new file mode 100644 index 00000000000..02152348111 --- /dev/null +++ b/libcxx/test/std/iterators/iterator.primitives/iterator.traits/empty.fail.cpp @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// <iterator> + +// struct iterator_traits +// { +// }; + +#include <iterator> +#include "test_macros.h" + +struct A {}; +struct NotAnIteratorEmpty {}; + +struct NotAnIteratorNoDifference +{ +// typedef int difference_type; + typedef A value_type; + typedef A* pointer; + typedef A& reference; + typedef std::forward_iterator_tag iterator_category; +}; + +struct NotAnIteratorNoValue +{ + typedef int difference_type; +// typedef A value_type; + typedef A* pointer; + typedef A& reference; + typedef std::forward_iterator_tag iterator_category; +}; + +struct NotAnIteratorNoPointer +{ + typedef int difference_type; + typedef A value_type; +// typedef A* pointer; + typedef A& reference; + typedef std::forward_iterator_tag iterator_category; +}; + +struct NotAnIteratorNoReference +{ + typedef int difference_type; + typedef A value_type; + typedef A* pointer; +// typedef A& reference; + typedef std::forward_iterator_tag iterator_category; +}; + +struct NotAnIteratorNoCategory +{ + typedef int difference_type; + typedef A value_type; + typedef A* pointer; + typedef A& reference; +// typedef std::forward_iterator_tag iterator_category; +}; + +int main() +{ + { + typedef std::iterator_traits<NotAnIteratorEmpty> T; + typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::value_type VT; // expected-error-re {{no type named 'value_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::pointer PT; // expected-error-re {{no type named 'pointer' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std::__1::iterator_traits<{{.+}}>}} + } + + { + typedef std::iterator_traits<NotAnIteratorNoDifference> T; + typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::value_type VT; // expected-error-re {{no type named 'value_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::pointer PT; // expected-error-re {{no type named 'pointer' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std::__1::iterator_traits<{{.+}}>}} + } + + { + typedef std::iterator_traits<NotAnIteratorNoValue> T; + typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::value_type VT; // expected-error-re {{no type named 'value_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::pointer PT; // expected-error-re {{no type named 'pointer' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std::__1::iterator_traits<{{.+}}>}} + } + + { + typedef std::iterator_traits<NotAnIteratorNoPointer> T; + typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::value_type VT; // expected-error-re {{no type named 'value_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::pointer PT; // expected-error-re {{no type named 'pointer' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std::__1::iterator_traits<{{.+}}>}} + } + + { + typedef std::iterator_traits<NotAnIteratorNoReference> T; + typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::value_type VT; // expected-error-re {{no type named 'value_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::pointer PT; // expected-error-re {{no type named 'pointer' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std::__1::iterator_traits<{{.+}}>}} + } + + { + typedef std::iterator_traits<NotAnIteratorNoCategory> T; + typedef T::difference_type DT; // expected-error-re {{no type named 'difference_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::value_type VT; // expected-error-re {{no type named 'value_type' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::pointer PT; // expected-error-re {{no type named 'pointer' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::reference RT; // expected-error-re {{no type named 'reference' in 'std::__1::iterator_traits<{{.+}}>}} + typedef T::iterator_category CT; // expected-error-re {{no type named 'iterator_category' in 'std::__1::iterator_traits<{{.+}}>}} + } +} diff --git a/libcxx/test/std/iterators/iterator.primitives/iterator.traits/iterator.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/iterator.traits/iterator.pass.cpp index 38f7c0b6b83..34f430ff3ee 100644 --- a/libcxx/test/std/iterators/iterator.primitives/iterator.traits/iterator.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/iterator.traits/iterator.pass.cpp @@ -39,5 +39,6 @@ int main() static_assert((std::is_same<It::difference_type, int>::value), ""); static_assert((std::is_same<It::value_type, A>::value), ""); static_assert((std::is_same<It::pointer, A*>::value), ""); + static_assert((std::is_same<It::reference, A&>::value), ""); static_assert((std::is_same<It::iterator_category, std::forward_iterator_tag>::value), ""); } |