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