GCC Code Coverage Report


Directory: gridformat/
File: gridformat/common/iterator_facades.hpp
Date: 2024-11-10 16:24:00
Exec Total Coverage
Lines: 57 57 100.0%
Functions: 291 363 80.2%
Branches: 7 10 70.0%

Line Branch Exec Source
1 // SPDX-FileCopyrightText: 2022-2023 Dennis Gläser <dennis.glaeser@iws.uni-stuttgart.de>
2 // SPDX-License-Identifier: MIT
3 /*!
4 * \file
5 * \ingroup Common
6 * \brief Iterator facades implemented by means of CRTP.
7 */
8 #ifndef GRIDFORMAT_COMMON_ITERATOR_FACADES_HPP_
9 #define GRIDFORMAT_COMMON_ITERATOR_FACADES_HPP_
10
11 #include <compare>
12 #include <cstddef>
13 #include <iterator>
14 #include <type_traits>
15
16 #include <gridformat/common/concepts.hpp>
17 #include <gridformat/common/detail/crtp.hpp>
18
19 namespace GridFormat {
20
21 //! \addtogroup Common
22 //! @{
23
24 /*!
25 * \brief Gateway for granting the iterator facades access to
26 * the iterator implementations. Iterator implementations
27 * are expected to provide a set of functions, depending
28 * on the type of iterator that is modeled. It is recommended
29 * to put these functions in private scope, and make IteratorAccess
30 * a friend of the implementation such that the facades can
31 * request access via this class.
32 */
33 class IteratorAccess {
34 public:
35 template<typename IteratorImpl>
36 924501 static decltype(auto) dereference(IteratorImpl* impl) {
37 924501 return impl->_dereference();
38 }
39
40 template<typename IteratorImpl>
41 1231669 static void increment(IteratorImpl* impl) {
42 1231669 return impl->_increment();
43 }
44
45 template<typename IteratorImpl>
46 2 static void decrement(IteratorImpl* impl) {
47 2 return impl->_decrement();
48 }
49
50 template<typename IteratorImpl>
51 7 static void advance(IteratorImpl* impl, std::signed_integral auto n) {
52 7 return impl->_advance(n);
53 }
54
55 template<std::signed_integral Difference, typename IteratorImpl1, typename IteratorImpl2>
56 8 static Difference distance(IteratorImpl1* lhs, IteratorImpl2* rhs) {
57 8 return lhs->_distance_to(*rhs);
58 }
59
60 template<typename IteratorImpl1, typename IteratorImpl2>
61 676007 static bool equal(IteratorImpl1* lhs, IteratorImpl2* rhs) {
62 676007 return lhs->_is_equal(*rhs);
63 }
64 };
65
66 /*!
67 * \brief Base class for all iterator facades.
68 * \tparam Impl The derived (implementation) type
69 * \tparam IteratorTag The iterator category tag
70 * \tparam ValueType The type over which it is iterated
71 * \tparam Reference The reference type returned after dereferencing
72 * \tparam Difference The type to express differences between two iterators
73 */
74 template<typename Impl,
75 typename IteratorTag,
76 typename ValueType,
77 typename Reference = ValueType&,
78 typename Pointer = std::remove_reference_t<Reference>*,
79 typename Difference = std::ptrdiff_t>
80 class IteratorFacade
81 : public Detail::CRTPBase<Impl> {
82 static constexpr bool is_bidirectional = std::derived_from<IteratorTag, std::bidirectional_iterator_tag>;
83 static constexpr bool is_random_access = std::derived_from<IteratorTag, std::random_access_iterator_tag>;
84
85 public:
86 using iterator_category = IteratorTag;
87 using value_type = ValueType;
88 using difference_type = Difference;
89 using pointer = Pointer;
90 using reference = Reference;
91
92 //! Test for equality against another iterator implementation
93 template<typename I, typename T, typename V, typename R, typename D>
94 676007 friend bool operator==(const IteratorFacade& lhs, const IteratorFacade<I, T, V, R, D>& rhs) {
95 676007 return IteratorAccess::equal(
96 lhs._pimpl(),
97 Detail::cast_to_impl_ptr<const I>(&rhs)
98 676007 );
99 }
100
101 //! Test for inequality against another iterator implementation
102 template<typename I, typename T, typename V, typename R, typename D>
103 73491 friend bool operator!=(const IteratorFacade& lhs, const IteratorFacade<I, T, V, R, D>& rhs) {
104 73491 return !(lhs == rhs);
105 }
106
107 924491 Reference operator*() const {
108 924491 return IteratorAccess::dereference(this->_pimpl());
109 }
110
111 5 Pointer operator->() const {
112 static_assert(std::is_lvalue_reference_v<Reference>);
113 5 return &(IteratorAccess::dereference(this->_pimpl()));
114 }
115
116 629750 Impl& operator++() {
117 629750 IteratorAccess::increment(this->_pimpl());
118 629750 return this->_impl();
119 }
120
121 1 Impl operator++(int) {
122 1 auto cpy(this->_impl());
123 1 IteratorAccess::increment(this->_pimpl());
124 1 return cpy;
125 }
126
127 2 Impl& operator--() requires(is_bidirectional) {
128 2 IteratorAccess::decrement(this->_pimpl());
129 2 return this->_impl();
130 }
131
132 Impl operator--(int) requires(is_bidirectional) {
133 auto cpy(this->_impl());
134 IteratorAccess::decrement(this->_pimpl());
135 return cpy;
136 }
137
138 2 Reference operator[](Difference n) const requires(is_random_access) {
139
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 auto cpy(this->_impl());
140
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 cpy += n;
141
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 return *cpy;
142 }
143
144 5 Impl& operator+=(Difference n) requires(is_random_access) {
145 5 IteratorAccess::advance(this->_pimpl(), n);
146 5 return this->_impl();
147 }
148
149 2 Impl& operator-=(Difference n) requires(is_random_access) {
150 2 IteratorAccess::advance(this->_pimpl(), -n);
151 2 return this->_impl();
152 }
153
154 2 Impl operator+(Difference n) const requires(is_random_access) {
155 2 auto cpy(this->_impl());
156 2 cpy += n;
157 2 return cpy;
158 }
159
160 1 Impl operator-(Difference n) const requires(is_random_access) {
161 1 auto cpy(this->_impl());
162 1 cpy -= n;
163 1 return cpy;
164 }
165
166 1 friend Impl operator+(Difference n, const IteratorFacade& it) requires(is_random_access) {
167 1 return it + n;
168 }
169
170 template<Concepts::Interoperable<Impl> I, typename T, typename V, typename R, typename D>
171 8 friend auto operator-(const IteratorFacade& lhs,
172 const IteratorFacade<I, T, V, R, D>& rhs) requires(is_random_access) {
173 if constexpr (std::is_convertible_v<I, Impl>)
174 8 return IteratorAccess::distance<Difference>(
175 Detail::cast_to_impl_ptr<const Impl>(&rhs),
176 lhs._pimpl()
177 8 );
178 else
179 return IteratorAccess::distance<D>(
180 rhs._pimpl(),
181 Detail::cast_to_impl_ptr<const I>(&lhs)
182 );
183 }
184
185 template<Concepts::Interoperable<Impl> I, typename T, typename V, typename R, typename D>
186 6 friend std::strong_ordering operator<=>(const IteratorFacade& lhs,
187 const IteratorFacade<I, T, V, R, D>& rhs) requires(is_random_access) {
188 6 const auto d = lhs - rhs;
189
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
6 return d <=> decltype(d){0};
190 }
191 };
192
193 /*!
194 * \brief Base class to turn a type into a forward iterator by means of CRTP.
195 * \tparam Impl The derived (implementation) type
196 * \tparam ValueType The type over which it is iterated
197 * \tparam Reference The reference type returned after dereferencing
198 * \tparam Difference The type to express differences between two iterators
199 */
200 template<typename Impl,
201 typename ValueType,
202 typename Reference = ValueType&,
203 typename Pointer = std::remove_reference_t<Reference>*,
204 typename Difference = std::ptrdiff_t>
205 using ForwardIteratorFacade = IteratorFacade<Impl,
206 std::forward_iterator_tag,
207 ValueType,
208 Reference,
209 Pointer,
210 Difference>;
211
212 /*!
213 * \brief Base class to turn a type into a bidirectional iterator by means of CRTP.
214 * \tparam Impl The derived (implementation) type
215 * \tparam ValueType The type over which it is iterated
216 * \tparam Reference The reference type returned after dereferencing
217 * \tparam Difference The type to express differences between two iterators
218 */
219 template<typename Impl,
220 typename ValueType,
221 typename Reference = ValueType&,
222 typename Pointer = std::remove_reference_t<Reference>*,
223 typename Difference = std::ptrdiff_t>
224 using BidirectionalIteratorFacade = IteratorFacade<Impl,
225 std::bidirectional_iterator_tag,
226 ValueType,
227 Reference,
228 Pointer,
229 Difference>;
230
231 /*!
232 * \brief Base class to turn a type into a random-access iterator by means of CRTP.
233 * \tparam Impl The derived (implementation) type
234 * \tparam ValueType The type over which it is iterated
235 * \tparam Reference The reference type returned after dereferencing
236 * \tparam Difference The type to express differences between two iterators
237 */
238 template<typename Impl,
239 typename ValueType,
240 typename Reference = ValueType&,
241 typename Pointer = std::remove_reference_t<Reference>*,
242 typename Difference = std::ptrdiff_t>
243 using RandomAccessIteratorFacade = IteratorFacade<Impl,
244 std::random_access_iterator_tag,
245 ValueType,
246 Reference,
247 Pointer,
248 Difference>;
249
250 //! @} end Common group
251
252 } // end namespace GridFormat
253
254 #endif // GRIDFORMAT_COMMON_ITERATOR_FACADES_HPP_
255