c++c++20

c++20 ranges view to vector


Now that the C++20 ranges implementation is actually here and released under GCC 10.2, I would like to know how to convert a ranges view back to an actual container, like a vector. I've found this question ( Range view to std::vector ) that asked the same thing for the pre-release version but I would like to know if since its been released, have there been any new methods made to convert from a view to a container? Or is that single answer on that question still the best solution?


Solution

  • I know this says C++20, but going forward the answer is C++23's std::ranges::to. It is a function template that has various ways to use it, including pipe or function (std::ranges::to<std::vector>(intsView) or intsView | std::ranges::to<std::vector>()), and implicit or explicit value-type (std::ranges::to<std::set>(intsView) or std::ranges::to<std::set<int>>(intView)). It also supports allocators. We have an implementation of roughly this in our codebase and use it all the time. There are so many cases that you want to collect a bunch of values together into a container, and std::ranges::to provides a great, concise, expressive API for doing exactly that. It even supports maps:

    // Project out the "foo" field of this->m_database
    auto map = std::ranges::to<absl::flat_hash_map>(
        this->m_database | std::views::transform([&](const auto& row) {
            return std::pair{row.first, row.second.foo}; 
        })
    );