14

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.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Related? https://stackoverflow.com/questions/55950955/why-does-the-upcoming-ranges-library-not-support-container-initialization-from-a – StoryTeller - Unslander Monica Dec 23 '19 at 08:55
  • Per StoryTeller: apparent duplicate of [Why does the upcoming Ranges library not support container initialization from a range?](https://stackoverflow.com/questions/55950955/why-does-the-upcoming-ranges-library-not-support-container-initialization-from-a)—but note that ballot resolution may yet change the answer! – Davis Herring Dec 23 '19 at 15:41
  • @DavisHerring What could change? [P1206](https://wg21.link/p1206) wasn't considered for 20 to begin with and I don't think there are any NB comments left open here? [P1391](https://wg21.link/p1391) was adopted _without_ the range constructor (despite the misleading example). – Barry Dec 23 '19 at 16:18
  • @Barry: LEWG [so forwarded it](https://github.com/cplusplus/papers/issues/145) in Kona, but I guess I misinterpreted recent reflector traffic about it. – Davis Herring Dec 23 '19 at 16:33
  • @DavisHerring Oh, I missed that it was discussed _twice_ - I scrolled down to the the 4-7 poll and thought that was that. – Barry Dec 23 '19 at 16:56

1 Answers1

11

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.

Barry
  • 286,269
  • 29
  • 621
  • 977