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 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 // UNSUPPORTED: libcpp-no-concepts 11 // UNSUPPORTED: gcc-10 12 13 // constexpr counted_iterator& operator++(); 14 // decltype(auto) operator++(int); 15 // constexpr counted_iterator operator++(int) 16 // requires forward_iterator<I>; 17 18 #include <iterator> 19 20 #include "test_macros.h" 21 #include "test_iterators.h" 22 23 #ifndef TEST_HAS_NO_EXCEPTIONS 24 template <class It> 25 class ThrowsOnInc 26 { 27 It it_; 28 29 public: 30 typedef std::input_iterator_tag iterator_category; 31 typedef typename std::iterator_traits<It>::value_type value_type; 32 typedef typename std::iterator_traits<It>::difference_type difference_type; 33 typedef It pointer; 34 typedef typename std::iterator_traits<It>::reference reference; 35 36 constexpr It base() const {return it_;} 37 38 ThrowsOnInc() = default; 39 explicit constexpr ThrowsOnInc(It it) : it_(it) {} 40 41 constexpr reference operator*() const {return *it_;} 42 43 constexpr ThrowsOnInc& operator++() {throw 42;} 44 constexpr ThrowsOnInc operator++(int) {throw 42;} 45 }; 46 #endif // TEST_HAS_NO_EXCEPTIONS 47 48 struct InputOrOutputArchetype { 49 using difference_type = int; 50 51 int *ptr; 52 53 constexpr int operator*() const { return *ptr; } 54 constexpr void operator++(int) { ++ptr; } 55 constexpr InputOrOutputArchetype& operator++() { ++ptr; return *this; } 56 }; 57 58 template<class Iter> 59 concept PlusEnabled = requires(Iter& iter) { 60 iter++; 61 ++iter; 62 }; 63 64 constexpr bool test() { 65 int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 66 67 { 68 using Counted = std::counted_iterator<forward_iterator<int*>>; 69 std::counted_iterator iter(forward_iterator<int*>{buffer}, 8); 70 71 assert(iter++ == Counted(forward_iterator<int*>{buffer}, 8)); 72 assert(++iter == Counted(forward_iterator<int*>{buffer + 2}, 6)); 73 74 ASSERT_SAME_TYPE(decltype(iter++), Counted); 75 ASSERT_SAME_TYPE(decltype(++iter), Counted&); 76 } 77 { 78 using Counted = std::counted_iterator<random_access_iterator<int*>>; 79 std::counted_iterator iter(random_access_iterator<int*>{buffer}, 8); 80 81 assert(iter++ == Counted(random_access_iterator<int*>{buffer}, 8)); 82 assert(++iter == Counted(random_access_iterator<int*>{buffer + 2}, 6)); 83 84 ASSERT_SAME_TYPE(decltype(iter++), Counted); 85 ASSERT_SAME_TYPE(decltype(++iter), Counted&); 86 } 87 88 { 89 static_assert( PlusEnabled< std::counted_iterator<random_access_iterator<int*>>>); 90 static_assert(!PlusEnabled<const std::counted_iterator<random_access_iterator<int*>>>); 91 } 92 93 return true; 94 } 95 96 int main(int, char**) { 97 test(); 98 static_assert(test()); 99 100 int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 101 102 { 103 using Counted = std::counted_iterator<InputOrOutputArchetype>; 104 std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8); 105 106 iter++; 107 assert((++iter).base().ptr == buffer + 2); 108 109 ASSERT_SAME_TYPE(decltype(iter++), void); 110 ASSERT_SAME_TYPE(decltype(++iter), Counted&); 111 } 112 { 113 using Counted = std::counted_iterator<cpp20_input_iterator<int*>>; 114 std::counted_iterator iter(cpp20_input_iterator<int*>{buffer}, 8); 115 116 iter++; 117 assert(++iter == Counted(cpp20_input_iterator<int*>{buffer + 2}, 6)); 118 119 ASSERT_SAME_TYPE(decltype(iter++), void); 120 ASSERT_SAME_TYPE(decltype(++iter), Counted&); 121 } 122 #ifndef TEST_HAS_NO_EXCEPTIONS 123 { 124 using Counted = std::counted_iterator<ThrowsOnInc<int*>>; 125 std::counted_iterator iter(ThrowsOnInc<int*>{buffer}, 8); 126 try { 127 (void)iter++; 128 assert(false); 129 } catch (int x) { 130 assert(x == 42); 131 assert(iter.count() == 8); 132 } 133 134 ASSERT_SAME_TYPE(decltype(iter++), ThrowsOnInc<int*>); 135 ASSERT_SAME_TYPE(decltype(++iter), Counted&); 136 } 137 #endif // TEST_HAS_NO_EXCEPTIONS 138 139 return 0; 140 } 141