0

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. (auto x = int(0);). How do I do this for a view, please?

Andrew
  • 626
  • 6
  • 16
  • @frank Yes, I'm aware of that. I use this convention as I find it more intuitive. However, I don't know what type ranges::views would be hence my question. Do you know by any chance? – Andrew Jun 17 '21 at 22:26
  • I think the best you can do would be `std::variant vi;`, but I would personally rather revisit the design in general instead of going down that rabbit hole. –  Jun 17 '21 at 22:26
  • @frank I see. There are terms there that I'm not familiar with (although I get the gist). I need to have a read up about variant and decltype. – Andrew Jun 17 '21 at 22:32

1 Answers1

3

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);
}