如何在不最初定义的情况下为 ranges::view 定义类型?

How to define a type for a ranges::view without defining it initially?

我需要根据变量指定不同的 ranges::view。如:

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

但问题是 auto 无法确定类型,所以我需要定义它,因为我已经为 x 定义了 int 类型。 (auto x = int(0);)。请问我该怎么做才能看到?

通常,您会希望通过在可以正确推断之前不声明 vi 来完全避免这种情况,这并不像您想象的那样具有约束力:

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

话虽这么说,如果有人降落在这里并真的把自己画在角落里,仍然值得回答这个问题。

您可以使用 decltype() 来标识将要使用的类型,然后使用 std::variant<> 使 vi 成为可以容纳其中任何一个的类型:

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