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