xref: /llvm-project/libcxx/test/std/iterators/predef.iterators/counted.iterator/increment.pass.cpp (revision 2a5ba4fb895931b7dc86f4304b0e64153a1175d4)
12c545131Sphilnik777 //===----------------------------------------------------------------------===//
22c545131Sphilnik777 //
32c545131Sphilnik777 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42c545131Sphilnik777 // See https://llvm.org/LICENSE.txt for license information.
52c545131Sphilnik777 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62c545131Sphilnik777 //
72c545131Sphilnik777 //===----------------------------------------------------------------------===//
82c545131Sphilnik777 
92c545131Sphilnik777 // UNSUPPORTED: c++03, c++11, c++14, c++17
102c545131Sphilnik777 
112c545131Sphilnik777 // constexpr counted_iterator& operator++();
12*2a5ba4fbSXiaoyang Liu // constexpr decltype(auto) operator++(int);
132c545131Sphilnik777 // constexpr counted_iterator operator++(int)
142c545131Sphilnik777 //   requires forward_iterator<I>;
152c545131Sphilnik777 
162c545131Sphilnik777 #include <iterator>
172c545131Sphilnik777 
182c545131Sphilnik777 #include "test_macros.h"
192c545131Sphilnik777 #include "test_iterators.h"
202c545131Sphilnik777 
212c545131Sphilnik777 #ifndef TEST_HAS_NO_EXCEPTIONS
222c545131Sphilnik777 template <class It>
232c545131Sphilnik777 class ThrowsOnInc
242c545131Sphilnik777 {
252c545131Sphilnik777     It it_;
262c545131Sphilnik777 
272c545131Sphilnik777 public:
282c545131Sphilnik777     typedef          std::input_iterator_tag                   iterator_category;
292c545131Sphilnik777     typedef typename std::iterator_traits<It>::value_type      value_type;
302c545131Sphilnik777     typedef typename std::iterator_traits<It>::difference_type difference_type;
312c545131Sphilnik777     typedef It                                                 pointer;
322c545131Sphilnik777     typedef typename std::iterator_traits<It>::reference       reference;
332c545131Sphilnik777 
base() const342c545131Sphilnik777     constexpr It base() const {return it_;}
352c545131Sphilnik777 
362c545131Sphilnik777     ThrowsOnInc() = default;
ThrowsOnInc(It it)372c545131Sphilnik777     explicit constexpr ThrowsOnInc(It it) : it_(it) {}
382c545131Sphilnik777 
operator *() const392c545131Sphilnik777     constexpr reference operator*() const {return *it_;}
402c545131Sphilnik777 
operator ++()412c545131Sphilnik777     constexpr ThrowsOnInc& operator++() {throw 42;}
operator ++(int)422c545131Sphilnik777     constexpr ThrowsOnInc operator++(int) {throw 42;}
432c545131Sphilnik777 };
442c545131Sphilnik777 #endif // TEST_HAS_NO_EXCEPTIONS
452c545131Sphilnik777 
462c545131Sphilnik777 struct InputOrOutputArchetype {
472c545131Sphilnik777   using difference_type = int;
482c545131Sphilnik777 
492c545131Sphilnik777   int *ptr;
502c545131Sphilnik777 
operator *InputOrOutputArchetype512c545131Sphilnik777   constexpr int operator*() const { return *ptr; }
operator ++InputOrOutputArchetype522c545131Sphilnik777   constexpr void operator++(int) { ++ptr; }
operator ++InputOrOutputArchetype532c545131Sphilnik777   constexpr InputOrOutputArchetype& operator++() { ++ptr; return *this; }
542c545131Sphilnik777 };
552c545131Sphilnik777 
562c545131Sphilnik777 template<class Iter>
572c545131Sphilnik777 concept PlusEnabled = requires(Iter& iter) {
582c545131Sphilnik777   iter++;
592c545131Sphilnik777   ++iter;
602c545131Sphilnik777 };
612c545131Sphilnik777 
test()622c545131Sphilnik777 constexpr bool test() {
632c545131Sphilnik777   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
642c545131Sphilnik777 
652c545131Sphilnik777   {
66*2a5ba4fbSXiaoyang Liu     using Counted = std::counted_iterator<InputOrOutputArchetype>;
67*2a5ba4fbSXiaoyang Liu     std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8);
68*2a5ba4fbSXiaoyang Liu 
69*2a5ba4fbSXiaoyang Liu     iter++;
70*2a5ba4fbSXiaoyang Liu     assert((++iter).base().ptr == buffer + 2);
71*2a5ba4fbSXiaoyang Liu 
72*2a5ba4fbSXiaoyang Liu     ASSERT_SAME_TYPE(decltype(iter++), void);
73*2a5ba4fbSXiaoyang Liu     ASSERT_SAME_TYPE(decltype(++iter), Counted&);
74*2a5ba4fbSXiaoyang Liu   }
75*2a5ba4fbSXiaoyang Liu   {
76*2a5ba4fbSXiaoyang Liu     using Counted = std::counted_iterator<cpp20_input_iterator<int*>>;
77*2a5ba4fbSXiaoyang Liu     std::counted_iterator iter(cpp20_input_iterator<int*>{buffer}, 8);
78*2a5ba4fbSXiaoyang Liu 
79*2a5ba4fbSXiaoyang Liu     iter++;
80*2a5ba4fbSXiaoyang Liu     assert(++iter == Counted(cpp20_input_iterator<int*>{buffer + 2}, 6));
81*2a5ba4fbSXiaoyang Liu 
82*2a5ba4fbSXiaoyang Liu     ASSERT_SAME_TYPE(decltype(iter++), void);
83*2a5ba4fbSXiaoyang Liu     ASSERT_SAME_TYPE(decltype(++iter), Counted&);
84*2a5ba4fbSXiaoyang Liu   }
85*2a5ba4fbSXiaoyang Liu   {
862c545131Sphilnik777     using Counted = std::counted_iterator<forward_iterator<int*>>;
872c545131Sphilnik777     std::counted_iterator iter(forward_iterator<int*>{buffer}, 8);
882c545131Sphilnik777 
892c545131Sphilnik777     assert(iter++ == Counted(forward_iterator<int*>{buffer}, 8));
902c545131Sphilnik777     assert(++iter == Counted(forward_iterator<int*>{buffer + 2}, 6));
912c545131Sphilnik777 
922c545131Sphilnik777     ASSERT_SAME_TYPE(decltype(iter++), Counted);
932c545131Sphilnik777     ASSERT_SAME_TYPE(decltype(++iter), Counted&);
942c545131Sphilnik777   }
952c545131Sphilnik777   {
962c545131Sphilnik777     using Counted = std::counted_iterator<random_access_iterator<int*>>;
972c545131Sphilnik777     std::counted_iterator iter(random_access_iterator<int*>{buffer}, 8);
982c545131Sphilnik777 
992c545131Sphilnik777     assert(iter++ == Counted(random_access_iterator<int*>{buffer}, 8));
1002c545131Sphilnik777     assert(++iter == Counted(random_access_iterator<int*>{buffer + 2}, 6));
1012c545131Sphilnik777 
1022c545131Sphilnik777     ASSERT_SAME_TYPE(decltype(iter++), Counted);
1032c545131Sphilnik777     ASSERT_SAME_TYPE(decltype(++iter), Counted&);
1042c545131Sphilnik777   }
1052c545131Sphilnik777 
1062c545131Sphilnik777   {
1072c545131Sphilnik777     static_assert( PlusEnabled<      std::counted_iterator<random_access_iterator<int*>>>);
1082c545131Sphilnik777     static_assert(!PlusEnabled<const std::counted_iterator<random_access_iterator<int*>>>);
1092c545131Sphilnik777   }
1102c545131Sphilnik777 
1112c545131Sphilnik777   return true;
1122c545131Sphilnik777 }
1132c545131Sphilnik777 
main(int,char **)1142c545131Sphilnik777 int main(int, char**) {
1152c545131Sphilnik777   test();
1162c545131Sphilnik777   static_assert(test());
1172c545131Sphilnik777 
1182c545131Sphilnik777 #ifndef TEST_HAS_NO_EXCEPTIONS
119*2a5ba4fbSXiaoyang Liu   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
1202c545131Sphilnik777   {
1212c545131Sphilnik777     using Counted = std::counted_iterator<ThrowsOnInc<int*>>;
1222c545131Sphilnik777     std::counted_iterator iter(ThrowsOnInc<int*>{buffer}, 8);
1232c545131Sphilnik777     try {
1242c545131Sphilnik777       (void)iter++;
1252c545131Sphilnik777       assert(false);
1262c545131Sphilnik777     } catch (int x) {
1272c545131Sphilnik777       assert(x == 42);
1282c545131Sphilnik777       assert(iter.count() == 8);
1292c545131Sphilnik777     }
1302c545131Sphilnik777 
1312c545131Sphilnik777     ASSERT_SAME_TYPE(decltype(iter++), ThrowsOnInc<int*>);
1322c545131Sphilnik777     ASSERT_SAME_TYPE(decltype(++iter), Counted&);
1332c545131Sphilnik777   }
1342c545131Sphilnik777 #endif // TEST_HAS_NO_EXCEPTIONS
1352c545131Sphilnik777 
1362c545131Sphilnik777   return 0;
1372c545131Sphilnik777 }
138