Coverage Report

Created: 2026-01-25 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/immer/immer/detail/iterator_facade.hpp
Line
Count
Source
1
//
2
// immer: immutable data structures for C++
3
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4
//
5
// This software is distributed under the Boost Software License, Version 1.0.
6
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7
//
8
9
#pragma once
10
11
#include <cstddef>
12
#include <iterator>
13
#include <type_traits>
14
15
namespace immer {
16
namespace detail {
17
18
struct iterator_core_access
19
{
20
    template <typename T>
21
    static decltype(auto) dereference(T&& x)
22
354k
    {
23
354k
        return x.dereference();
24
354k
    }
25
26
    template <typename T>
27
    static decltype(auto) increment(T&& x)
28
354k
    {
29
354k
        return x.increment();
30
354k
    }
31
32
    template <typename T>
33
    static decltype(auto) decrement(T&& x)
34
    {
35
        return x.decrement();
36
    }
37
38
    template <typename T1, typename T2>
39
    static decltype(auto) equal(T1&& x1, T2&& x2)
40
363k
    {
41
363k
        return x1.equal(x2);
42
363k
    }
43
44
    template <typename T, typename D>
45
    static decltype(auto) advance(T&& x, D d)
46
    {
47
        return x.advance(d);
48
    }
49
50
    template <typename T1, typename T2>
51
    static decltype(auto) distance_to(T1&& x1, T2&& x2)
52
    {
53
        return x1.distance_to(x2);
54
    }
55
};
56
57
/*!
58
 * Minimalistic reimplementation of boost::iterator_facade
59
 */
60
template <typename DerivedT,
61
          typename IteratorCategoryT,
62
          typename T,
63
          typename ReferenceT      = T&,
64
          typename DifferenceTypeT = std::ptrdiff_t,
65
          typename PointerT        = T*>
66
class iterator_facade
67
{
68
public:
69
    using iterator_category = IteratorCategoryT;
70
    using value_type        = T;
71
    using difference_type   = DifferenceTypeT;
72
    using pointer           = PointerT;
73
    using reference         = ReferenceT;
74
75
protected:
76
    using access_t = iterator_core_access;
77
78
    constexpr static auto is_random_access =
79
        std::is_base_of<std::random_access_iterator_tag,
80
                        IteratorCategoryT>::value;
81
    constexpr static auto is_bidirectional =
82
        std::is_base_of<std::bidirectional_iterator_tag,
83
                        IteratorCategoryT>::value;
84
85
    const DerivedT& derived() const
86
354k
    {
87
354k
        static_assert(std::is_base_of<iterator_facade, DerivedT>::value,
88
354k
                      "must pass a derived thing");
89
354k
        return *static_cast<const DerivedT*>(this);
90
354k
    }
91
    DerivedT& derived()
92
708k
    {
93
708k
        static_assert(std::is_base_of<iterator_facade, DerivedT>::value,
94
708k
                      "must pass a derived thing");
95
708k
        return *static_cast<DerivedT*>(this);
96
708k
    }
97
98
public:
99
354k
    ReferenceT operator*() const { return access_t::dereference(derived()); }
100
    PointerT operator->() const { return &access_t::dereference(derived()); }
101
102
    template <typename U = iterator_facade,
103
              typename std::enable_if_t<U::is_random_access, bool> = true>
104
    ReferenceT operator[](DifferenceTypeT n) const
105
    {
106
        return *(derived() + n);
107
    }
108
109
    friend bool operator==(const DerivedT& a, const DerivedT& b)
110
    {
111
        return access_t::equal(a, b);
112
    }
113
    friend bool operator!=(const DerivedT& a, const DerivedT& b)
114
363k
    {
115
363k
        return !access_t::equal(a, b);
116
363k
    }
117
118
    DerivedT& operator++()
119
354k
    {
120
354k
        access_t::increment(derived());
121
354k
        return derived();
122
354k
    }
123
    DerivedT operator++(int)
124
    {
125
        auto tmp = derived();
126
        access_t::increment(derived());
127
        return tmp;
128
    }
129
130
    template <
131
        typename U                      = iterator_facade,
132
        typename std::enable_if_t<U::is_bidirectional || U::is_random_access,
133
                                  bool> = true>
134
    DerivedT& operator--()
135
    {
136
        access_t::decrement(derived());
137
        return derived();
138
    }
139
    template <
140
        typename U                      = iterator_facade,
141
        typename std::enable_if_t<U::is_bidirectional || U::is_random_access,
142
                                  bool> = true>
143
    DerivedT operator--(int)
144
    {
145
        auto tmp = derived();
146
        access_t::decrement(derived());
147
        return tmp;
148
    }
149
150
    DerivedT& operator+=(DifferenceTypeT n)
151
    {
152
        access_t::advance(derived(), n);
153
        return derived();
154
    }
155
    DerivedT& operator-=(DifferenceTypeT n)
156
    {
157
        access_t::advance(derived(), -n);
158
        return derived();
159
    }
160
161
    template <typename U = iterator_facade,
162
              typename std::enable_if_t<U::is_random_access, bool> = true>
163
    DerivedT operator+(DifferenceTypeT n) const
164
    {
165
        auto tmp = derived();
166
        return tmp += n;
167
    }
168
    template <typename U = iterator_facade,
169
              typename std::enable_if_t<U::is_random_access, bool> = true>
170
    friend DerivedT operator+(DifferenceTypeT n, const DerivedT& i)
171
    {
172
        return i + n;
173
    }
174
    template <typename U = iterator_facade,
175
              typename std::enable_if_t<U::is_random_access, bool> = true>
176
    DerivedT operator-(DifferenceTypeT n) const
177
    {
178
        auto tmp = derived();
179
        return tmp -= n;
180
    }
181
182
    template <typename U = iterator_facade,
183
              typename std::enable_if_t<U::is_random_access, bool> = true>
184
    friend DifferenceTypeT operator-(const DerivedT& a, const DerivedT& b)
185
    {
186
        return access_t::distance_to(b, a);
187
    }
188
189
    template <typename U = iterator_facade,
190
              typename std::enable_if_t<U::is_random_access, bool> = true>
191
    friend bool operator<(const DerivedT& a, const DerivedT& b)
192
193
    {
194
        return access_t::distance_to(a, b) > 0;
195
    }
196
    template <typename U = iterator_facade,
197
              typename std::enable_if_t<U::is_random_access, bool> = true>
198
    friend bool operator<=(const DerivedT& a, const DerivedT& b)
199
    {
200
        return access_t::distance_to(a, b) >= 0;
201
    }
202
    template <typename U = iterator_facade,
203
              typename std::enable_if_t<U::is_random_access, bool> = true>
204
    friend bool operator>(const DerivedT& a, const DerivedT& b)
205
206
    {
207
        return access_t::distance_to(a, b) < 0;
208
    }
209
    template <typename U = iterator_facade,
210
              typename std::enable_if_t<U::is_random_access, bool> = true>
211
    friend bool operator>=(const DerivedT& a, const DerivedT& b)
212
    {
213
        return access_t::distance_to(a, b) <= 0;
214
    }
215
};
216
217
} // namespace detail
218
} // namespace immer