File: increment.cpp

package info (click to toggle)
llvm-toolchain-13 1%3A13.0.1-6~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,418,812 kB
  • sloc: cpp: 5,290,827; ansic: 996,570; asm: 544,593; python: 188,212; objc: 72,027; lisp: 30,291; f90: 25,395; sh: 24,900; javascript: 9,780; pascal: 9,398; perl: 7,484; ml: 5,432; awk: 3,523; makefile: 2,892; xml: 953; cs: 573; fortran: 539
file content (140 lines) | stat: -rw-r--r-- 4,113 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: gcc-10

// constexpr counted_iterator& operator++();
// decltype(auto) operator++(int);
// constexpr counted_iterator operator++(int)
//   requires forward_iterator<I>;

#include <iterator>

#include "test_macros.h"
#include "test_iterators.h"

#ifndef TEST_HAS_NO_EXCEPTIONS
template <class It>
class ThrowsOnInc
{
    It it_;

public:
    typedef          std::input_iterator_tag                   iterator_category;
    typedef typename std::iterator_traits<It>::value_type      value_type;
    typedef typename std::iterator_traits<It>::difference_type difference_type;
    typedef It                                                 pointer;
    typedef typename std::iterator_traits<It>::reference       reference;

    constexpr It base() const {return it_;}

    ThrowsOnInc() = default;
    explicit constexpr ThrowsOnInc(It it) : it_(it) {}

    constexpr reference operator*() const {return *it_;}

    constexpr ThrowsOnInc& operator++() {throw 42;}
    constexpr ThrowsOnInc operator++(int) {throw 42;}
};
#endif // TEST_HAS_NO_EXCEPTIONS

struct InputOrOutputArchetype {
  using difference_type = int;

  int *ptr;

  constexpr int operator*() const { return *ptr; }
  constexpr void operator++(int) { ++ptr; }
  constexpr InputOrOutputArchetype& operator++() { ++ptr; return *this; }
};

template<class Iter>
concept PlusEnabled = requires(Iter& iter) {
  iter++;
  ++iter;
};

constexpr bool test() {
  int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};

  {
    using Counted = std::counted_iterator<forward_iterator<int*>>;
    std::counted_iterator iter(forward_iterator<int*>{buffer}, 8);

    assert(iter++ == Counted(forward_iterator<int*>{buffer}, 8));
    assert(++iter == Counted(forward_iterator<int*>{buffer + 2}, 6));

    ASSERT_SAME_TYPE(decltype(iter++), Counted);
    ASSERT_SAME_TYPE(decltype(++iter), Counted&);
  }
  {
    using Counted = std::counted_iterator<random_access_iterator<int*>>;
    std::counted_iterator iter(random_access_iterator<int*>{buffer}, 8);

    assert(iter++ == Counted(random_access_iterator<int*>{buffer}, 8));
    assert(++iter == Counted(random_access_iterator<int*>{buffer + 2}, 6));

    ASSERT_SAME_TYPE(decltype(iter++), Counted);
    ASSERT_SAME_TYPE(decltype(++iter), Counted&);
  }

  {
    static_assert( PlusEnabled<      std::counted_iterator<random_access_iterator<int*>>>);
    static_assert(!PlusEnabled<const std::counted_iterator<random_access_iterator<int*>>>);
  }

  return true;
}

int main(int, char**) {
  test();
  static_assert(test());

  int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};

  {
    using Counted = std::counted_iterator<InputOrOutputArchetype>;
    std::counted_iterator iter(InputOrOutputArchetype{buffer}, 8);

    iter++;
    assert((++iter).base().ptr == buffer + 2);

    ASSERT_SAME_TYPE(decltype(iter++), void);
    ASSERT_SAME_TYPE(decltype(++iter), Counted&);
  }
  {
    using Counted = std::counted_iterator<cpp20_input_iterator<int*>>;
    std::counted_iterator iter(cpp20_input_iterator<int*>{buffer}, 8);

    iter++;
    assert(++iter == Counted(cpp20_input_iterator<int*>{buffer + 2}, 6));

    ASSERT_SAME_TYPE(decltype(iter++), void);
    ASSERT_SAME_TYPE(decltype(++iter), Counted&);
  }
#ifndef TEST_HAS_NO_EXCEPTIONS
  {
    using Counted = std::counted_iterator<ThrowsOnInc<int*>>;
    std::counted_iterator iter(ThrowsOnInc<int*>{buffer}, 8);
    try {
      (void)iter++;
      assert(false);
    } catch (int x) {
      assert(x == 42);
      assert(iter.count() == 8);
    }

    ASSERT_SAME_TYPE(decltype(iter++), ThrowsOnInc<int*>);
    ASSERT_SAME_TYPE(decltype(++iter), Counted&);
  }
#endif // TEST_HAS_NO_EXCEPTIONS

  return 0;
}