Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will we be able to construct containers with views in C++20?

Ranges are coming to C++ with the C++20 standard version.

My question: Will we be able to construct (existing) standard-library containers with any range? And more importantly, with range views?

For example, will this:

#include <vector>
#include <iostream>
#include <ranges>

int main() {
    auto sq = [](int x) { return x * x; };
    std::vector<int> vec { 3, 4, 5 };
    std::vector<int> squares { std::ranges::views::transform(vec, sq) };
    for(auto i : squares) { std::cout << i << ' '; }
    std::cout << std::endl;
}

be a valid program which prints 9 16 25?

This compiles with the ranges-v3 library, for what that's worth.

like image 722
einpoklum Avatar asked Dec 23 '19 08:12

einpoklum


1 Answers

My question: Will we be able to construct (existing) standard-library containers with any range? And more importantly, with range views?

No. The only standard library component that is constructible from an arbitrary range that meets the correct criteria is std::span<T>.

The direction the standard library will likely go with is the one that range-v3 is also going towards (note that the linked example from range-v3 does compile but warns on a deprecated conversion) - using a helper to do conversions for you:

std::vector<int> squares =
    std::ranges::views::transform(vec, sq) | std::ranges::to<std::vector>;

One of the reasons to not go in the direction of range constructors can be seen from the very example you're using:

std::vector<int> squares { std::ranges::views::transform(vec, sq) };

Consider how different that declaration is from these two:

std::vector v { std::ranges::views::transform(vec, sq) };
std::vector w ( std::ranges::views::transform(vec, sq) );

v would necessarily be a vector<transform_view<...>> containing a single transform_view, while w would be a vector<int>.

Moreover, adding more, carefully constrained container constructors to the standard library isn't going to help third-party container types anyway - while a facility like ranges::to works perfectly well in all cases.

like image 84
Barry Avatar answered Oct 23 '22 05:10

Barry