I need to specify different ranges::view
s depending upon a variable. Such as:
#include <ranges>
#include <vector>
auto main() -> int
{
std::vector<double> xs = { 1.0, 2.0, 3.0, 4.0, 5.0 };
auto x = int(0);
auto vi;
if(x == 0)
vi = xs | std::ranges::views::all;
else
vi = xs | std::ranges::views::drop(2);
}
but the problem is auto
can't determine a type so I need to define it as I've defined the int
type for x
. (i.e., auto x = int(0);
).
How do I do this for a view?
Normally, you would want to avoid this altogether by not declaring vi
until it can be inferred properly, which is not as constraining as you might think:
#include <ranges>
#include <vector>
#include <iostream>
template<typename RangeT>
void foo(const RangeT& vi) {
for(auto & v: vi) {
std::cout << v << "\n";
}
}
auto main() -> int
{
std::vector<double> xs = { 1.0, 2.0, 3.0, 4.0, 5.0 };
auto x = int(0);
if(x == 0) {
auto vi = xs | std::ranges::views::all;
foo(vi);
}
else {
auto vi = xs | std::ranges::views::drop(2);
foo(vi);
}
}
That being said, in case anyone lands here and has really painted themselves in a corner, it's still worth answering the question as asked.
You can use decltype()
to identify the types that will be used, and then use std::variant<>
to make vi
a type that can hold either of them:
#include <ranges>
#include <vector>
#include <variant>
#include <iostream>
auto main() -> int
{
std::vector<double> xs = { 1.0, 2.0, 3.0, 4.0, 5.0 };
auto x = int(0);
using vi_all = decltype(xs | std::ranges::views::all);
using vi_drop_2 = decltype(xs | std::ranges::views::drop(2));
std::variant<vi_all, vi_drop_2> vi;
if(x == 0)
vi = xs | std::ranges::views::all;
else
vi = xs | std::ranges::views::drop(2);
std::visit([](auto& vi){
for(auto& v: vi) {
std::cout << v << "\n";
}
}, vi);
}