-
Notifications
You must be signed in to change notification settings - Fork 446
Expand file tree
/
Copy pathvtr_range.h
More file actions
94 lines (87 loc) · 2.86 KB
/
Copy pathvtr_range.h
File metadata and controls
94 lines (87 loc) · 2.86 KB
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
#pragma once
#include <iterator>
#include <ranges>
namespace vtr {
/**
* @brief The vtr::Range template models a range defined by two iterators of type T.
*
* It allows conveniently returning a range from a single function call
* without having to explicitly expose the underlying container, or make two
* explicit calls to retrieve the associated begin and end iterators.
* It also enables the easy use of range-based-for loops.
*
* For example:
*
* class My Data {
* public:
* typedef std::vector<int>::const_iterator my_iter;
* vtr::Range<my_iter> data();
* ...
* private:
* std::vector<int> data_;
* };
*
* ...
*
* MyDat my_data;
*
* //fill my_data
*
* for(int val : my_data.data()) {
* //work with values stored in my_data
* }
*
* The empty() and size() methods are convenience wrappers around the relevant
* iterator comparisons.
*
* Note that size() is only constant time if T is a random-access iterator!
*/
template<typename T>
class Range {
public:
///@brief constructor
constexpr Range(T b, T e)
: begin_(b)
, end_(e) {}
///@brief Return an iterator to the start of the range
constexpr T begin() noexcept { return begin_; }
///@brief Return an iterator to the end of the range
constexpr T end() noexcept { return end_; }
///@brief Return an iterator to the start of the range (immutable)
constexpr const T begin() const noexcept { return begin_; }
///@brief Return an iterator to the end of the range (immutable)
constexpr const T end() const noexcept { return end_; }
///@brief Return true if empty
constexpr bool empty() const noexcept { return begin_ == end_; }
///@brief Return the range size
constexpr size_t size() const { return std::distance(begin_, end_); }
private:
T begin_;
T end_;
};
/**
* @brief Creates a vtr::Range from a pair of iterators.
*
* Unlike using the vtr::Range() constructor (which requires specifying
* the template type T, using vtr::make_range() infers T from the arguments.
*
* Example usage:
* auto my_range = vtr::make_range(my_vec.begin(), my_vec.end());
*/
template<typename T>
constexpr auto make_range(T b, T e) { return Range<T>(b, e); }
/**
* @brief Creates a vtr::Range from a container
*/
template<typename Container>
inline auto make_range(const Container& c) { return make_range(std::begin(c), std::end(c)); }
} // namespace vtr
/**
* @brief Mark vtr::Range as a borrowed range.
*
* A vtr::Range only holds a pair of iterators, so those iterators stay valid
* after the Range object itself is destroyed. This lets temporary ranges be
* passed directly to std::ranges algorithms and views (e.g. std::views::filter).
*/
template<typename T>
inline constexpr bool std::ranges::enable_borrowed_range<vtr::Range<T>> = true;