0

I'm trying to read a vector in the reverse order using a ranges::subrange view but I'm confused about how it should work. I'm aware of ranges::reverse but I'm trying to avoid using this method as a personal preference and learning experience.

My non-working example code is here:

#include <algorithm>
#include <ranges>
#include <vector>
#include <iostream>

int main() {
    using namespace std::ranges;

    std::vector<int> v {1, 2, 3, 4};
    
    const auto [first, last] = range(v.rbegin(), v.rend());

    auto view = subrange(first, last - 1);

    for (auto n : view) {
        std::cout << n << ' ';
    }
}

This is how I imagine it should work but clearly, there is a distance between my imagination and reality. In some examples online I've seen ranges::equal_range being used to set the [first, last] iterators but I'm not interested in matching any values, just setting the iterators to rbegin and rend.

What ranges command should I be using to define the [first, last] iterators or how should I be using the range command correctly?

bolov
  • 72,283
  • 15
  • 145
  • 224
Andrew
  • 626
  • 6
  • 16
  • What is your expected result and what do you actually get? Why do you need a range to set the variables first and last? And why do you decrease 1 from last when creating the subrange view? – Amir Kirsh Jun 09 '21 at 21:19
  • Which type are you trying to create? `range` is a concept. – chris Jun 09 '21 at 21:20
  • @AmirKirsh I'm playing and learning. The expected results are to display 4,3,2. I want to use a range to set the values so that I can learn how to do it, for no other reason. I'm sure they can be set directly in the subrange statement. I decrease 1 from the last iterator to prove it can be done, for no other reason than that. Hope this helps. – Andrew Jun 09 '21 at 21:32
  • @chris I'm trying to create 2 reverse iterators that can be used in the subrange statement view below. I want the view to be in reverse order (less one element) of the original vector. – Andrew Jun 09 '21 at 21:35
  • @Andrew, I get that, but what specifically is `range(v.rbegin(), v.rend())` expected to do? `range` is a concept and has no executable code associated with it, so it can't _do_ anything, nor be called or constructed. You already have `v.rbegin()` and `v.rend()` there, so I'm not sure what more this line is supposed to be doing with them. – chris Jun 09 '21 at 21:37
  • @chris I realise now that the range statement is erroneous (it didn't compile anyway). I'd like to know what statement should replace it so that the first last reverse iterators are created and can be used in the subrange statement below. I couldn't find anything really appropriate in the docs. – Andrew Jun 09 '21 at 21:42
  • @Andrew, There's nothing extra to do, just use them. `v.rbegin()` and `v.rend()` are already "created" reverse iterators. – chris Jun 09 '21 at 21:47

1 Answers1

4

Given that you want 4,3,2, you're looking for:

v | views::drop(1) | views::reverse

That is, drop the first element (the 1), and then reverse the remainder.


If you really want to avoid the range adapters, you could do:

subrange(v.rbegin(), v.rend() - 1)

to accomplish the same thing. All subrange does is combine two iterators (or an iterator and a sentinel) together into a range.


Demo of both.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • I'm aware of these concepts and know that they work as I mentioned in the first few sentences of my problem. I'm more interested in learning how to do a subrange. Thanks for your answer though. – Andrew Jun 09 '21 at 21:38
  • @Andrew Outside of the nonsensical line in your original code declaring `first` and `last`, you already got it. I'm showing the correct formulation in my answer. – Barry Jun 09 '21 at 21:44
  • I appreciate you have given me the answer to the subrange part and I thank you for that. I need to know what I should replace the 'nonsensical line' with in order to create the iterators outside of the subrange statement. I may be confusing something that is common to standard C++ with what I imagined ranges would do. Thanks for your patience. – Andrew Jun 09 '21 at 21:50
  • @Andrew Why do you need to create the iterators outside of the subrange statement? I suppose you could do `auto first = v.rbegin(); auto last = v.rend() - 1; auto v = ranges::subrange(first, last);` but that just seems a lot more tedious than simply `auto v = ranges::subrange(v.rbegin(), v.rend() - 1);` – Barry Jun 09 '21 at 21:53
  • Fair enough. One of the examples I was looking at confused me then (I'd tried finding it again but failed). I'll accept this as the answer. Thanks very much. – Andrew Jun 09 '21 at 22:00