Is there any better way to drop last element in container using c 20 ranges than reverse it twice?
#include <iostream>
#include <vector>
#include <ranges>
int main()
{
std::vector<int> foo{1, 2, 3, 4, 5, 6};
for (const auto& d: foo | std::ranges::views::reverse
| std::ranges::views::drop(1)
| std::ranges::views::reverse)
{
std::cout << d << std::endl;
}
}
CodePudding user response:
What you need is views::drop_last
which comes from p2214 and has a priority of Tier 2.
As the paper says:
We’ll go through the other potential range adapters in this family and discuss how they could be implemented in terms of existing adapters:
take_last(N)
anddrop_last(N)
.views::take_last(N)
is equivalent toviews::reverse | views::take(N) | views::reverse
. But this is somewhat expensive, especially for non-common views. For random-access, sized ranges, we’re probably wantr | views::take_last(N)
to evaluate asr | views::drop(r.size() - N)
, and that desire is really the crux of this whole question — is the equivalent version good enough or should we want to do it right?
Since vector
is a random-access, sized range, you can just do
for (const auto& d: foo | std::views::take(foo.size() - 1))
{
std::cout << d << std::endl;
}
CodePudding user response:
How about using span
?
#include <iostream>
#include <span>
#include <vector>
int main() {
std::vector<int> foo{1, 2, 3, 4, 5, 6};
for (const auto& d : std::span(foo.begin(), foo.end() - 1)) {
std::cout << d << '\n';
}
}