This was asked in op's comment section, but I think I will respond it in the answer section:
The Ranges library seems promising, but I'm a little apprehensive about this returning auto.
Remember that even with the addition of auto
, C++ is a strongly typed language. In your case, since you are returning evens
, then the return type will be the same type of evens
. (technically it will be the value type of evens
, but evens
was a value type anyways)
In fact, you probably really don't want to type out the return type manually: std::ranges::filter_view<std::ranges::ref_view<const std::vector<int>>, MyClass::getEvens() const::<decltype([](int i) {return ! (i % 2);})>>
(141 characters)
- As mentioned by @Caleth in the comment, in fact, this wouldn't work either as
evens
was a lambda defined inside the function, and the type of two different lambdas will be different even if they were basically the same, so there's literally no way of getting the full return type here.
While there might be debates on whether to use auto
or not in different cases, but I believe most people would just use auto
here. Plus your evens
was declared with auto
too, typing the type out would just make it less readable here.
So what are my options if I want to access a subset (for instance even numbers)? Are there any other approaches I should be considering, with or without the Ranges library?
Depends on how you would access the returned data and the type of the data, you might consider returning std::vector<T*>
.
views
are really supposed to be viewed from start to end. While you could use views::drop
and views::take
to limit to a single element, it doesn't provide a subscript operator (yet).
There will also be computational differences. vector
need to be computed beforehand, where views
are computed while iterating. So when you do:
for(auto i : myObject.getEven())
{
std::cout << i;
}
Under the hood, it is basically doing:
for(auto i : myObject.vec)
{
if(!(i % 2)) std::cout << i;
}
Depends on the amount of data, and the complexity of computations, views
might be a lot faster, or about the same as the vector
method. Plus you can easily apply multiple filters on the same range without iterating through the data multiple times.
In the end, you can always store the view
in a vector
:
std::vector<int> vec2(evens.begin(), evens.end());
So my suggestions is, if you have the ranges library, then you should use it.
If not, then vector<T>
, vector<T*>
, vector<index>
depending on the size and copiability of T.