11
11
#include < testing-utils/catch.hpp>
12
12
#include < util/range.h>
13
13
14
+ // / Trivial example template function requiring a container to have a
15
+ // / `value_type`.
16
+ template <typename containert>
17
+ typename containert::value_type front (containert container)
18
+ {
19
+ return *container.begin ();
20
+ }
21
+
14
22
SCENARIO (" range tests" , " [core][util][range]" )
15
23
{
16
24
GIVEN (" A vector with three strings" )
@@ -21,15 +29,15 @@ SCENARIO("range tests", "[core][util][range]")
21
29
list.emplace_back (" acdef" );
22
30
THEN (" Use range-for to compute the total length" )
23
31
{
24
- auto range = make_range (list);
32
+ const auto range = make_range (list);
25
33
std::size_t total_length = 0 ;
26
34
for (const auto &s : range)
27
35
total_length += s.length ();
28
36
REQUIRE (total_length == 12 );
29
37
}
30
38
THEN (" Use map to compute individual lengths" )
31
39
{
32
- auto length_range =
40
+ const auto length_range =
33
41
make_range (list).map ([](const std::string &s) { return s.length (); });
34
42
auto it = length_range.begin ();
35
43
REQUIRE (*it == 3 );
@@ -42,16 +50,27 @@ SCENARIO("range tests", "[core][util][range]")
42
50
}
43
51
THEN (" Filter using lengths" )
44
52
{
45
- auto filtered_range = make_range (list).filter (
53
+ const auto filtered_range = make_range (list).filter (
46
54
[&](const std::string &s) { return s.length () == 4 ; });
47
55
auto it = filtered_range.begin ();
48
56
REQUIRE (*it == " cdef" );
49
57
++it;
50
58
REQUIRE (it == filtered_range.end ());
51
59
}
60
+ THEN (
61
+ " A const instance of a `filter_iteratort` can mutate the input "
62
+ " collection." )
63
+ {
64
+ const auto it =
65
+ make_range (list)
66
+ .filter ([&](const std::string &s) { return s.length () == 3 ; })
67
+ .begin ();
68
+ *it += " x" ;
69
+ REQUIRE (*list.begin () == " abcx" );
70
+ }
52
71
THEN (" Filter, map and use range-for on the same list" )
53
72
{
54
- auto range =
73
+ const auto range =
55
74
make_range (list)
56
75
.filter ([&](const std::string &s) -> bool { return s[0 ] == ' a' ; })
57
76
.map ([&](const std::string &s) { return s.length (); });
@@ -64,6 +83,72 @@ SCENARIO("range tests", "[core][util][range]")
64
83
REQUIRE (total == 8 );
65
84
}
66
85
}
86
+ GIVEN (" A const vector of ints" )
87
+ {
88
+ const std::vector<int > input{1 , 2 , 3 , 4 };
89
+ THEN (" Filter the vector using range." )
90
+ {
91
+ const auto odds_range =
92
+ make_range (input).filter ([](const int number) { return number % 2 ; });
93
+ const std::vector<int > odds{odds_range.begin (), odds_range.end ()};
94
+ const std::vector<int > expected_odds{1 , 3 };
95
+ REQUIRE (odds == expected_odds);
96
+ }
97
+ THEN (
98
+ " The unit testing template function requiring `value_type` works with "
99
+ " `std::vector`." )
100
+ {
101
+ REQUIRE (front (input) == 1 );
102
+ }
103
+ THEN (
104
+ " A range can be used with a template function expecting a container "
105
+ " which has a `value_type`." )
106
+ {
107
+ REQUIRE (front (make_range (input)) == 1 );
108
+ }
109
+ THEN (" Map over the vector using range." )
110
+ {
111
+ const auto plus_one_range =
112
+ make_range (input).map ([](const int number) { return number + 1 ; });
113
+ const std::vector<int > plus_one_collection{plus_one_range.begin (),
114
+ plus_one_range.end ()};
115
+ const std::vector<int > expected_output{2 , 3 , 4 , 5 };
116
+ REQUIRE (plus_one_collection == expected_output);
117
+ };
118
+ }
119
+ GIVEN (" Two const vectors of ints" )
120
+ {
121
+ const std::vector<int > input1{1 , 2 };
122
+ const std::vector<int > input2{3 , 4 };
123
+ THEN (" Concat the vectors using range." )
124
+ {
125
+ const auto range = make_range (input1).concat (make_range (input2));
126
+ const std::vector<int > output{range.begin (), range.end ()};
127
+ const std::vector<int > expected{1 , 2 , 3 , 4 };
128
+ REQUIRE (output == expected);
129
+ };
130
+ }
131
+ GIVEN (" Two non-const vectors of ints." )
132
+ {
133
+ std::vector<int > input1{1 , 2 };
134
+ std::vector<int > input2{3 , 4 };
135
+ THEN (
136
+ " Const instances of `concat_iteratort` should enable the input "
137
+ " collections to be mutated." )
138
+ {
139
+ const auto concat_range = make_range (input1).concat (make_range (input2));
140
+ int x = 5 ;
141
+ for (auto it = concat_range.begin (); it != concat_range.end (); ++it, ++x)
142
+ {
143
+ const auto const_it = it;
144
+ *const_it = x;
145
+ }
146
+ std::vector<int > expected_result1{5 , 6 };
147
+ std::vector<int > expected_result2{7 , 8 };
148
+ REQUIRE (input1 == expected_result1);
149
+ REQUIRE (input2 == expected_result2);
150
+ }
151
+ }
67
152
}
68
153
69
154
class move_onlyt
@@ -98,13 +183,13 @@ SCENARIO(
98
183
input.emplace_back (i);
99
184
THEN (" Values from a range of made from the vector can be moved." )
100
185
{
101
- auto input_range = make_range (input);
186
+ const auto input_range = make_range (input);
102
187
move_onlyt destination{std::move (*input_range.begin ())};
103
188
REQUIRE (destination.value == 1 );
104
189
}
105
190
THEN (" A range of made from the vector can be filtered." )
106
191
{
107
- auto odds_filter = make_range (input).filter (is_odd);
192
+ const auto odds_filter = make_range (input).filter (is_odd);
108
193
const std::size_t total =
109
194
std::distance (odds_filter.begin (), odds_filter.end ());
110
195
REQUIRE (total == 5 );
0 commit comments