| 1 | //===----------------------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | // <iterator> |
| 10 | |
| 11 | // All of these became constexpr in C++17 |
| 12 | // |
| 13 | // template <InputIterator Iter, class Distance> |
| 14 | // constexpr void advance(Iter& i, Distance n); |
| 15 | // |
| 16 | // template <BidirectionalIterator Iter, class Distance> |
| 17 | // constexpr void advance(Iter& i, Distance n); |
| 18 | // |
| 19 | // template <RandomAccessIterator Iter, class Distance> |
| 20 | // constexpr void advance(Iter& i, Distance n); |
| 21 | |
| 22 | |
| 23 | // TODO: test_iterators.h includes <ranges>, and <ranges> includes <chrono> and <atomic>. |
| 24 | // Lots of implementation headers under <__chrono/> and <atomic> has signed to unsigned conversion, |
| 25 | // which will trigger the -Wsign-conversion warning. |
| 26 | // Once those headers are fixed, enable the -Wsign-conversion for this test by removing |
| 27 | // <TODO:Remove brackets> below |
| 28 | |
| 29 | // Make sure we catch forced conversions to the difference_type if they happen. |
| 30 | // ADDITIONAL_COMPILE_FLAGS<TODO:Remove brackets>(gcc-style-warnings): -Wsign-conversion |
| 31 | |
| 32 | #include <iterator> |
| 33 | #include <cassert> |
| 34 | #include <cstddef> |
| 35 | #include <type_traits> |
| 36 | |
| 37 | #include "test_macros.h" |
| 38 | #include "test_iterators.h" |
| 39 | |
| 40 | template <class Distance, class It> |
| 41 | TEST_CONSTEXPR_CXX17 |
| 42 | void check_advance(It it, Distance n, It result) |
| 43 | { |
| 44 | static_assert(std::is_same<decltype(std::advance(it, n)), void>::value, "" ); |
| 45 | std::advance(it, n); |
| 46 | assert(it == result); |
| 47 | } |
| 48 | |
| 49 | TEST_CONSTEXPR_CXX17 bool tests() |
| 50 | { |
| 51 | const char* s = "1234567890" ; |
| 52 | |
| 53 | // Check with iterator_traits::difference_type |
| 54 | { |
| 55 | typedef std::iterator_traits<const char*>::difference_type Distance; |
| 56 | check_advance<Distance>(cpp17_input_iterator<const char*>(s), 10, cpp17_input_iterator<const char*>(s+10)); |
| 57 | check_advance<Distance>(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10)); |
| 58 | check_advance<Distance>(bidirectional_iterator<const char*>(s+5), 5, bidirectional_iterator<const char*>(s+10)); |
| 59 | check_advance<Distance>(bidirectional_iterator<const char*>(s+5), -5, bidirectional_iterator<const char*>(s)); |
| 60 | check_advance<Distance>(random_access_iterator<const char*>(s+5), 5, random_access_iterator<const char*>(s+10)); |
| 61 | check_advance<Distance>(random_access_iterator<const char*>(s+5), -5, random_access_iterator<const char*>(s)); |
| 62 | check_advance<Distance>(s+5, 5, s+10); |
| 63 | check_advance<Distance>(s+5, -5, s); |
| 64 | } |
| 65 | |
| 66 | // Also check with other distance types |
| 67 | { |
| 68 | typedef int Distance; |
| 69 | check_advance<Distance>(cpp17_input_iterator<const char*>(s), 10, cpp17_input_iterator<const char*>(s+10)); |
| 70 | check_advance<Distance>(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10)); |
| 71 | check_advance<Distance>(bidirectional_iterator<const char*>(s), 10, bidirectional_iterator<const char*>(s+10)); |
| 72 | check_advance<Distance>(random_access_iterator<const char*>(s), 10, random_access_iterator<const char*>(s+10)); |
| 73 | } |
| 74 | |
| 75 | // Check with unsigned distance types to catch signedness-change issues |
| 76 | { |
| 77 | typedef std::size_t Distance; |
| 78 | check_advance<Distance>(cpp17_input_iterator<const char*>(s), 10u, cpp17_input_iterator<const char*>(s+10)); |
| 79 | check_advance<Distance>(forward_iterator<const char*>(s), 10u, forward_iterator<const char*>(s+10)); |
| 80 | check_advance<Distance>(bidirectional_iterator<const char*>(s), 10u, bidirectional_iterator<const char*>(s+10)); |
| 81 | check_advance<Distance>(random_access_iterator<const char*>(s), 10u, random_access_iterator<const char*>(s+10)); |
| 82 | } |
| 83 | |
| 84 | return true; |
| 85 | } |
| 86 | |
| 87 | int main(int, char**) |
| 88 | { |
| 89 | tests(); |
| 90 | #if TEST_STD_VER >= 17 |
| 91 | static_assert(tests(), "" ); |
| 92 | #endif |
| 93 | return 0; |
| 94 | } |
| 95 | |