Skip to content

Commit 20cc2dd

Browse files
committed
Provide const dereference of filter / concat iterators only
Deferencing a `const` iterator which refers to a non-const value should enable mutation of that value. This is consistent with how iterators in the STL work. It means that we only need to provide a single const overload of these operators, not both the const and non-const variations. So the benefit of this commit is better consistency with the STL and fewer operator overloads to maintain.
1 parent 7a5ff90 commit 20cc2dd

File tree

2 files changed

+34
-28
lines changed

2 files changed

+34
-28
lines changed

src/util/range.h

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,12 @@ class filter_iteratort
143143
return tmp;
144144
}
145145

146-
reference operator*()
146+
reference operator*() const
147147
{
148148
return *underlying;
149149
}
150150

151-
pointer operator->()
152-
{
153-
return &(*underlying);
154-
}
155-
156-
const value_type &operator*() const
157-
{
158-
return *underlying;
159-
}
160-
161-
const value_type *operator->() const
151+
pointer operator->() const
162152
{
163153
return &(*underlying);
164154
}
@@ -245,28 +235,14 @@ struct concat_iteratort
245235
return tmp;
246236
}
247237

248-
reference operator*()
249-
{
250-
if(first_begin == first_end)
251-
return *second_begin;
252-
return *first_begin;
253-
}
254-
255-
pointer operator->()
256-
{
257-
if(first_begin == first_end)
258-
return &(*second_begin);
259-
return &(*first_begin);
260-
}
261-
262-
const value_type &operator*() const
238+
reference operator*() const
263239
{
264240
if(first_begin == first_end)
265241
return *second_begin;
266242
return *first_begin;
267243
}
268244

269-
const value_type *operator->() const
245+
pointer operator->() const
270246
{
271247
if(first_begin == first_end)
272248
return &(*second_begin);

unit/util/range.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ SCENARIO("range tests", "[core][util][range]")
5757
++it;
5858
REQUIRE(it == filtered_range.end());
5959
}
60+
THEN("A const filter iterator can mutate the input collection.")
61+
{
62+
const auto it =
63+
make_range(list)
64+
.filter([&](const std::string &s) { return s.length() == 3; })
65+
.begin();
66+
*it += "x";
67+
REQUIRE(*list.begin() == "abcx");
68+
}
6069
THEN("Filter, map and use range-for on the same list")
6170
{
6271
const auto range =
@@ -117,6 +126,27 @@ SCENARIO("range tests", "[core][util][range]")
117126
REQUIRE(output == expected);
118127
};
119128
}
129+
GIVEN("Two non-const vectors of ints.")
130+
{
131+
std::vector<int> input1{1, 2};
132+
std::vector<int> input2{3, 4};
133+
THEN(
134+
"Const concat iterators should enable the input collections to be "
135+
"mutated.")
136+
{
137+
const auto concat_range = make_range(input1).concat(make_range(input2));
138+
int x = 5;
139+
for(auto it = concat_range.begin(); it != concat_range.end(); ++it, ++x)
140+
{
141+
const auto const_it = it;
142+
*const_it = x;
143+
}
144+
std::vector<int> expected_result1{5, 6};
145+
std::vector<int> expected_result2{7, 8};
146+
REQUIRE(input1 == expected_result1);
147+
REQUIRE(input2 == expected_result2);
148+
}
149+
}
120150
}
121151

122152
class move_onlyt

0 commit comments

Comments
 (0)