I have a container that I want to filter.
I also need the index of the items later.
For that I want to use something like this:
auto items_to_remove = items | ranges::view::enumerate | ranges::view::filter(/*???*/);
What type do I have to use for the filter function?
CodePudding user response:
Use std::pair<int, T>
. .first
is the index. .second
is the element.
int main() {
auto v = std::vector{0, 1, 23, 3, 42, 50, 81, 4, -1};
auto f = [](std::pair<int, int> p) { return p.first % 2 == 0 && p.second >= 10; };
for (auto [i, e] : v | views::enumerate | views::filter(f)) {
std::cout << i << " -> " << e << "\n";
}
}
CodePudding user response:
Adding an enumerate::view
makes the element that is passed to the filter a
ranges::common_pair<size_t, int&>&
So, just take the common_pair
by const&
.
auto f = [](const ranges::common_pair<size_t, int&>& pair) {
// filter on pair.first to filter on the index
// filter on pair.second to filter on the actual value in the vector
};
or simply:
auto f = [](auto&& pair) { ... }
Then
for (auto&&[idx, element] : v | views::enumerate | views::filter(f)) {
element = 100; // elements are mutable here
std::cout << idx << ' ' << element << '\n';
}
CodePudding user response:
You should use auto lambdas with ranges, adding it static asserts if necessary.
If you don't want a copy happening you can simply have a predicate that takes its argument by value.
auto pred = [](auto pair) -> bool { return /*do something with T&*/ pair.second; };
The instantiated type of pair
will be ranges::common_pair<size_t, T&>
which you can copy around without copying the underlying T
. You can call pair.second
to get a T&
in you predicate.
Shower around the following static assert just to be sure or delete the copy constructor for T
because it is a very annoying when this copy turns out to be your bug.
std::vector<std::optional<T>> elements;
for (auto [index, opt] : elements
| ranges::views::filter([](auto pair) -> bool { return pair.second; })
)
{
static_assert(std::is_reference_v<decltype(opt)>);
opt->MethodOfT();
}
To understand why opt
is a reference here see my question