tcbrindle / NanoRange

Range-based goodness for C++17
Boost Software License 1.0
358 stars 28 forks source link

nano::to_vector ? #91

Closed Guekka closed 4 years ago

Guekka commented 4 years ago

Sorry if it is obvious, but I did not find a way to convert a range to a vector. Simple example: std::vector<int> = nano::views::iota(0, 1000); // | nano::to_vector ?

//In Range-v3 return ranges::views::iota(0, starterSize) | ranges::to_vector;

So, is it possible? Thanks

tcbrindle commented 4 years ago

There is no std::ranges::to_vector in C++20, so there isn't one in NanoRange :)

This should work though?

template <typename T, typename Rng>
std::vector<T> to_vector(Rng&& rng)
{
    auto v = nano::views::common(std::forward<Rng>(rng));
    return std::vector<T>(v.begin(), v.end());
}

template <typename T>
auto to_vector()
{
    return nano::detail::rao_proxy{[](auto&& rng) { 
        return ::to_vector<T>(std::forward<decltype(rng)>(rng));
    }};
}

https://godbolt.org/z/oFe8Lx

Guekka commented 4 years ago

Having to specify explicitly the type of the vector is not very convenient. Out of curiosity, don't ranges have a value_type member or an equivalent? But thank you for this quick answer, this will work perfectly

tcbrindle commented 4 years ago

There is indeed a nano::range_value_t alias template which you can use to get a range's value type, but using that as the default template argument gets tricky.

An alternative is to use CTAD, for example:

template <typename T = void, typename Rng>
auto to_vector(Rng&& rng)
{
    auto v = nano::views::common(std::forward<Rng>(rng));

    if constexpr (nano::same_as<T, void>) {
        return std::vector(v.begin(), v.end());
    } else {
        return std::vector<T>(v.begin(), v.end());
    }
}

template <typename T = void>
auto to_vector()
{
    return nano::detail::rao_proxy{[](auto&& rng) { 
        return ::to_vector<T>(std::forward<decltype(rng)>(rng));
    }};
}

int main()
{
    // Using explicit type
    auto vec1 = nano::views::iota(1, 10) | to_vector<int>();

    // Using CTAD
    auto vec2 = nano::views::iota(1, 10) | to_vector();
}

https://godbolt.org/z/wszbZd

Guekka commented 4 years ago

This is exactly what I was looking for, thank you! Maybe you could write that somewhere, it might be useful for someone else? I'm closing the issue anyway, thanks again.