CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
range.h
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Range
4
5Author: Romain Brenguier, romain.brenguier@diffblue.com
6
7\*******************************************************************/
8
13
14#ifndef CPROVER_UTIL_RANGE_H
15#define CPROVER_UTIL_RANGE_H
16
17#include <util/invariant.h>
18
19#include <functional>
20#include <memory>
21#include <type_traits>
22
25template <typename iteratort, typename outputt>
27{
28public:
29 using difference_type = typename iteratort::difference_type;
31 using pointer = const outputt *;
32 using reference = const outputt &;
33 using iterator_category = std::forward_iterator_tag;
34
35 bool operator==(const map_iteratort &other) const
36 {
37 return underlying == other.underlying;
38 }
39
40 bool operator!=(const map_iteratort &other) const
41 {
42 return !(this->underlying == other.underlying);
43 }
44
47 {
49 ++underlying;
51 current = std::make_shared<outputt>((*f)(*underlying));
52 return *this;
53 }
54
57 {
58 map_iteratort tmp(*this);
59 this->operator++();
60 return tmp;
61 }
62
64 {
65 return *current.get();
66 }
67
69 {
70 return &(*current.get());
71 }
72
73 const value_type &operator*() const
74 {
75 return *current.get();
76 }
77
78 const value_type *operator->() const
79 {
80 return &(*current.get());
81 }
82
83 explicit map_iteratort(
84 iteratort underlying,
85 iteratort underlying_end,
86 std::shared_ptr<
87 std::function<value_type(const typename iteratort::value_type &)>> f)
88 : underlying(std::move(underlying)),
90 f(std::move(f))
91 {
92 if(this->underlying != this->underlying_end)
93 current = std::make_shared<outputt>((*this->f)(*this->underlying));
94 }
95
96private:
97 iteratort underlying;
98 iteratort underlying_end;
99 std::shared_ptr<
100 std::function<value_type(const typename iteratort::value_type &)>>
102
105 std::shared_ptr<outputt> current = nullptr;
106};
107
110template <typename iteratort>
112{
113public:
114 using difference_type = typename iteratort::difference_type;
115 using value_type = typename iteratort::value_type;
116 using pointer = typename iteratort::pointer;
117 using reference = typename iteratort::reference;
118 using iterator_category = std::forward_iterator_tag;
119
120 bool operator==(const filter_iteratort &other) const
121 {
122 return underlying == other.underlying;
123 }
124
125 bool operator!=(const filter_iteratort &other) const
126 {
127 return !(this->underlying == other.underlying);
128 }
129
132 {
133 ++underlying;
135 return *this;
136 }
137
140 {
141 filter_iteratort tmp(*this);
142 this->operator++();
143 return tmp;
144 }
145
147 {
148 return *underlying;
149 }
150
152 {
153 return &(*underlying);
154 }
155
164 std::shared_ptr<std::function<bool(const value_type &)>> f,
165 iteratort underlying,
166 iteratort end)
167 : underlying(std::move(underlying)),
168 underlying_end(std::move(end)),
169 f(std::move(f))
170 {
172 }
173
174private:
175 iteratort underlying;
176 const iteratort underlying_end;
177 std::shared_ptr<std::function<bool(const value_type &)>> f;
178
185 {
186 while(underlying != underlying_end && !(*f)(*underlying))
187 ++underlying;
188 }
189};
190
195template <typename first_iteratort, typename second_iteratort>
197{
198public:
199 using difference_type = typename first_iteratort::difference_type;
200 using value_type = typename first_iteratort::value_type;
201 using pointer = typename first_iteratort::pointer;
202 using reference = typename first_iteratort::reference;
203 using iterator_category = std::forward_iterator_tag;
204
205 static_assert(
206 std::is_same<value_type, typename first_iteratort::value_type>::value,
207 "Concatenated iterators should have the same value type");
208
209 bool operator==(const concat_iteratort &other) const
210 {
211 return first_begin == other.first_begin && first_end == other.first_end &&
212 second_begin == other.second_begin;
213 }
214
215 bool operator!=(const concat_iteratort &other) const
216 {
217 return !(*this == other);
218 }
219
222 {
224 ++second_begin;
225 else
226 ++first_begin;
227 return *this;
228 }
229
232 {
234 this->operator++();
235 return tmp;
236 }
237
239 {
241 return *second_begin;
242 return *first_begin;
243 }
244
246 {
248 return &(*second_begin);
249 return &(*first_begin);
250 }
251
261
262private:
266};
267
274template <
275 typename first_iteratort,
276 typename second_iteratort,
277 bool same_size = true>
279{
280public:
281 using difference_type = typename first_iteratort::difference_type;
282 using value_type = std::pair<
283 typename first_iteratort::value_type,
284 typename second_iteratort::value_type>;
287 using iterator_category = std::forward_iterator_tag;
288
289 bool operator==(const zip_iteratort &other) const
290 {
291 if(!same_size && end_reached() && other.end_reached())
292 return true;
293
294 return first_begin == other.first_begin && first_end == other.first_end &&
295 second_begin == other.second_begin && second_end == other.second_end;
296 }
297
298 bool operator!=(const zip_iteratort &other) const
299 {
300 return !(*this == other);
301 }
302
305 {
307 ++first_begin;
308 ++second_begin;
309 INVARIANT(
310 !same_size ||
312 "Zipped ranges should have the same size");
314 ? std::make_shared<value_type>(*first_begin, *second_begin)
315 : nullptr;
316 return *this;
317 }
318
321 {
323 this->operator++();
324 return tmp;
325 }
326
328 {
329 PRECONDITION(current != nullptr);
330 return *current;
331 }
332
334 {
335 return current.get();
336 }
337
354
355private:
360 std::shared_ptr<value_type> current = nullptr;
361
362 bool end_reached() const
363 {
364 if(same_size)
365 {
366 INVARIANT(
368 "Zip ranges should have same size");
369 return first_begin == first_end;
370 }
371 else
373 }
374};
375
394template <typename iteratort>
395struct ranget final
396{
397public:
398 using value_type = typename iteratort::value_type;
399
400 ranget(iteratort begin, iteratort end)
401 : begin_value(std::move(begin)), end_value(std::move(end))
402 {
403 }
404
406 filter(std::function<bool(const value_type &)> f)
407 {
408 auto shared_f = std::make_shared<decltype(f)>(std::move(f));
412 }
413
420 template <typename functiont>
421 auto map(functiont &&f)
422 {
423 using outputt = typename std::invoke_result<functiont, value_type>::type;
424 auto shared_f = std::make_shared<
425 std::function<outputt(const typename iteratort::value_type &)>>(
426 std::forward<functiont>(f));
427 auto map_begin =
431 std::move(map_begin), std::move(map_end));
432 }
433
434 template <typename other_iteratort>
445
449 template <bool same_size = true, typename other_iteratort>
460
461 template <bool same_size = true, typename containert>
462 auto zip(containert &container)
463 -> ranget<zip_iteratort<iteratort, decltype(container.begin()), same_size>>
464 {
465 return zip<same_size>(
466 ranget<decltype(container.begin())>{container.begin(), container.end()});
467 }
468
469 bool empty() const
470 {
471 return begin_value == end_value;
472 }
473
477 ranget<iteratort> drop(std::size_t count) &&
478 {
479 for(; count > 0 && begin_value != end_value; --count)
480 ++begin_value;
481 return ranget<iteratort>{std::move(begin_value), std::move(end_value)};
482 }
483
487 ranget<iteratort> drop(std::size_t count) const &
488 {
489 return ranget<iteratort>{begin(), end()}.drop(count);
490 }
491
492 iteratort begin() const
493 {
494 return begin_value;
495 }
496
497 const iteratort &end() const
498 {
499 return end_value;
500 }
501
504 template <typename containert>
506 {
507 return containert(begin(), end());
508 }
509
510 template <typename containert>
511 operator containert() const
512 {
513 return collect<containert>();
514 }
515
516private:
517 iteratort begin_value;
518 iteratort end_value;
519};
520
521template <typename iteratort>
522ranget<iteratort> make_range(iteratort begin, iteratort end)
523{
524 return ranget<iteratort>(begin, end);
525}
526
527template <typename containert>
528auto make_range(containert &container) -> ranget<decltype(container.begin())>
529{
530 return ranget<decltype(container.begin())>(
531 container.begin(), container.end());
532}
533
537template <typename multimapt>
539equal_range(const multimapt &multimap, const typename multimapt::key_type &key)
540{
541 auto iterator_pair = multimap.equal_range(key);
542 return make_range(iterator_pair.first, iterator_pair.second);
543}
544
545#endif // CPROVER_UTIL_RANGE_H
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Iterator which only stops at elements for which some given function f is true.
Definition range.h:112
void point_to_first_to_peek()
Ensure that the underlying iterator is always positioned on an element for which f is true.
Definition range.h:184
reference operator*() const
Definition range.h:146
iteratort underlying
Definition range.h:175
typename iteratort::difference_type difference_type
Definition range.h:114
typename iteratort::value_type value_type
Definition range.h:115
typename iteratort::reference reference
Definition range.h:117
filter_iteratort(std::shared_ptr< std::function< bool(const value_type &)> > f, iteratort underlying, iteratort end)
Filter between underlying and end using f.
Definition range.h:163
typename iteratort::pointer pointer
Definition range.h:116
std::shared_ptr< std::function< bool(const value_type &)> > f
Definition range.h:177
bool operator==(const filter_iteratort &other) const
Definition range.h:120
bool operator!=(const filter_iteratort &other) const
Definition range.h:125
pointer operator->() const
Definition range.h:151
filter_iteratort operator++(int)
Postincrement operator.
Definition range.h:139
filter_iteratort & operator++()
Preincrement operator.
Definition range.h:131
const iteratort underlying_end
Definition range.h:176
std::forward_iterator_tag iterator_category
Definition range.h:118
Iterator which applies some given function f after each increment and returns its result on dereferen...
Definition range.h:27
value_type * operator->()
Definition range.h:68
const value_type & operator*() const
Definition range.h:73
std::shared_ptr< outputt > current
Stores the result of f at the current position of the iterator.
Definition range.h:105
iteratort underlying
Definition range.h:97
typename iteratort::difference_type difference_type
Definition range.h:29
outputt value_type
Definition range.h:30
bool operator==(const map_iteratort &other) const
Definition range.h:35
std::shared_ptr< std::function< value_type(const typename iteratort::value_type &)> > f
Definition range.h:101
bool operator!=(const map_iteratort &other) const
Definition range.h:40
map_iteratort operator++(int)
Postincrement operator.
Definition range.h:56
const value_type * operator->() const
Definition range.h:78
map_iteratort(iteratort underlying, iteratort underlying_end, std::shared_ptr< std::function< value_type(const typename iteratort::value_type &)> > f)
Definition range.h:83
iteratort underlying_end
Definition range.h:98
value_type & operator*()
Definition range.h:63
map_iteratort & operator++()
Preincrement operator.
Definition range.h:46
std::forward_iterator_tag iterator_category
Definition range.h:33
STL namespace.
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
ranget< typename multimapt::const_iterator > equal_range(const multimapt &multimap, const typename multimapt::key_type &key)
Utility function to make equal_range method of multimap easier to use by returning a ranget object.
Definition range.h:539
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
On increment, increments a first iterator and when the corresponding end iterator is reached,...
Definition range.h:197
typename first_iteratort::difference_type difference_type
Definition range.h:199
bool operator!=(const concat_iteratort &other) const
Definition range.h:215
reference operator*() const
Definition range.h:238
concat_iteratort operator++(int)
Postincrement operator.
Definition range.h:231
typename first_iteratort::reference reference
Definition range.h:202
typename first_iteratort::value_type value_type
Definition range.h:200
typename first_iteratort::pointer pointer
Definition range.h:201
concat_iteratort(first_iteratort first_begin, first_iteratort first_end, second_iteratort second_begin)
Definition range.h:252
first_iteratort first_end
Definition range.h:264
std::forward_iterator_tag iterator_category
Definition range.h:203
pointer operator->() const
Definition range.h:245
first_iteratort first_begin
Definition range.h:263
second_iteratort second_begin
Definition range.h:265
concat_iteratort & operator++()
Preincrement operator.
Definition range.h:221
bool operator==(const concat_iteratort &other) const
Definition range.h:209
A range is a pair of a begin and an end iterators.
Definition range.h:396
iteratort begin() const
Definition range.h:492
iteratort end_value
Definition range.h:518
ranget< zip_iteratort< iteratort, other_iteratort, same_size > > zip(ranget< other_iteratort > other)
Combine two ranges to make a range over pairs.
Definition range.h:451
auto zip(containert &container) -> ranget< zip_iteratort< iteratort, decltype(container.begin()), same_size > >
Definition range.h:462
ranget< iteratort > drop(std::size_t count) &&
Return an new range containing the same elements except for the first count elements.
Definition range.h:477
ranget< iteratort > drop(std::size_t count) const &
Return an new range containing the same elements except for the first count elements.
Definition range.h:487
ranget(iteratort begin, iteratort end)
Definition range.h:400
ranget< filter_iteratort< iteratort > > filter(std::function< bool(const value_type &)> f)
Definition range.h:406
iteratort begin_value
Definition range.h:517
const iteratort & end() const
Definition range.h:497
auto map(functiont &&f)
The type of elements contained in the resulting range is deduced from the return type of f.
Definition range.h:421
bool empty() const
Definition range.h:469
typename iteratort::value_type value_type
Definition range.h:398
containert collect() const
Constructs a collection containing the values, which this range iterates over.
Definition range.h:505
ranget< concat_iteratort< iteratort, other_iteratort > > concat(ranget< other_iteratort > other)
Definition range.h:436
Zip two ranges to make a range of pairs.
Definition range.h:279
typename first_iteratort::difference_type difference_type
Definition range.h:281
zip_iteratort(first_iteratort _first_begin, first_iteratort _first_end, second_iteratort _second_begin, second_iteratort _second_end)
Definition range.h:338
second_iteratort second_begin
Definition range.h:358
first_iteratort first_begin
Definition range.h:356
second_iteratort second_end
Definition range.h:359
bool operator!=(const zip_iteratort &other) const
Definition range.h:298
zip_iteratort operator++(int)
Postincrement operator.
Definition range.h:320
reference operator*() const
Definition range.h:327
first_iteratort first_end
Definition range.h:357
std::shared_ptr< value_type > current
Definition range.h:360
value_type * pointer
Definition range.h:285
pointer operator->() const
Definition range.h:333
std::forward_iterator_tag iterator_category
Definition range.h:287
value_type & reference
Definition range.h:286
zip_iteratort & operator++()
Preincrement operator.
Definition range.h:304
std::pair< typename first_iteratort::value_type, typename second_iteratort::value_type > value_type
Definition range.h:284
bool operator==(const zip_iteratort &other) const
Definition range.h:289
bool end_reached() const
Definition range.h:362