Home > Back-end >  What is the best way to drop last element using c 20 ranges
What is the best way to drop last element using c 20 ranges

Time:03-31

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) and drop_last(N). views::take_last(N) is equivalent to views::reverse | views::take(N) | views::reverse. But this is somewhat expensive, especially for non-common views. For random-access, sized ranges, we’re probably want r | views::take_last(N) to evaluate as r | 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';
  }
}
  • Related