diff --git a/libcxx/include/iterator b/libcxx/include/iterator --- a/libcxx/include/iterator +++ b/libcxx/include/iterator @@ -54,10 +54,8 @@ struct random_access_iterator_tag : public bidirectional_iterator_tag {}; // 27.4.3, iterator operations -// extension: second argument not conforming to C++03 -template // constexpr in C++17 - constexpr void advance(InputIterator& i, - typename iterator_traits::difference_type n); +template // constexpr in C++17 + constexpr void advance(InputIterator& i, Distance n); template // constexpr in C++17 constexpr typename iterator_traits::difference_type @@ -633,19 +631,17 @@ typedef _Category iterator_category; }; -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -void __advance(_InputIter& __i, - typename iterator_traits<_InputIter>::difference_type __n, input_iterator_tag) +void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) { for (; __n > 0; --__n) ++__i; } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -void __advance(_BiDirIter& __i, - typename iterator_traits<_BiDirIter>::difference_type __n, bidirectional_iterator_tag) +void __advance(_BiDirIter& __i, _Distance __n, bidirectional_iterator_tag) { if (__n >= 0) for (; __n > 0; --__n) @@ -655,18 +651,16 @@ --__i; } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -void __advance(_RandIter& __i, - typename iterator_traits<_RandIter>::difference_type __n, random_access_iterator_tag) +void __advance(_RandIter& __i, _Distance __n, random_access_iterator_tag) { __i += __n; } -template +template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 -void advance(_InputIter& __i, - typename iterator_traits<_InputIter>::difference_type __n) +void advance(_InputIter& __i, _Distance __n) { _LIBCPP_ASSERT(__n >= 0 || __is_cpp17_bidirectional_iterator<_InputIter>::value, "Attempt to advance(it, -n) on a non-bidi iterator"); diff --git a/libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/iterator.operations/advance.pass.cpp @@ -10,25 +10,29 @@ // All of these became constexpr in C++17 // -// template -// constexpr void advance(Iter& i, Iter::difference_type n); +// template +// constexpr void advance(Iter& i, Distance n); // -// template -// constexpr void advance(Iter& i, Iter::difference_type n); +// template +// constexpr void advance(Iter& i, Distance n); // -// template -// constexpr void advance(Iter& i, Iter::difference_type n); +// template +// constexpr void advance(Iter& i, Distance n); + +// Make sure we catch forced conversions to the difference_type if they happen. +// ADDITIONAL_COMPILER_FLAGS: -Wsign-conversion #include #include +#include #include #include "test_macros.h" #include "test_iterators.h" -template +template TEST_CONSTEXPR_CXX17 -void check_advance(It it, typename std::iterator_traits::difference_type n, It result) +void check_advance(It it, Distance n, It result) { static_assert(std::is_same::value, ""); std::advance(it, n); @@ -38,14 +42,21 @@ TEST_CONSTEXPR_CXX17 bool tests() { const char* s = "1234567890"; - check_advance(input_iterator(s), 10, input_iterator(s+10)); - check_advance(forward_iterator(s), 10, forward_iterator(s+10)); - check_advance(bidirectional_iterator(s+5), 5, bidirectional_iterator(s+10)); - check_advance(bidirectional_iterator(s+5), -5, bidirectional_iterator(s)); - check_advance(random_access_iterator(s+5), 5, random_access_iterator(s+10)); - check_advance(random_access_iterator(s+5), -5, random_access_iterator(s)); - check_advance(s+5, 5, s+10); - check_advance(s+5, -5, s); + typedef std::iterator_traits::difference_type Distance; + check_advance(input_iterator(s), 10, input_iterator(s+10)); + check_advance(forward_iterator(s), 10, forward_iterator(s+10)); + check_advance(bidirectional_iterator(s+5), 5, bidirectional_iterator(s+10)); + check_advance(bidirectional_iterator(s+5), -5, bidirectional_iterator(s)); + check_advance(random_access_iterator(s+5), 5, random_access_iterator(s+10)); + check_advance(random_access_iterator(s+5), -5, random_access_iterator(s)); + check_advance(s+5, 5, s+10); + check_advance(s+5, -5, s); + + // Also check with other distance types + check_advance(input_iterator(s), 10u, input_iterator(s+10)); + check_advance(forward_iterator(s), 10u, forward_iterator(s+10)); + check_advance(bidirectional_iterator(s), 10u, bidirectional_iterator(s+10)); + check_advance(random_access_iterator(s), 10u, random_access_iterator(s+10)); return true; }