Сможем ли мы создавать контейнеры с представлениями в C ++ 20?

10

Диапазоны идут к C ++ со стандартной версией C ++ 20.

Мой вопрос: сможем ли мы создать (существующие) контейнеры стандартной библиотеки с любым диапазоном? И что еще важнее, с диапазоном просмотров?

Например, будет ли это:

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

быть действительной программой, которая печатает 9 16 25?

Это компилируется с библиотеком range-v3 , для чего это стоит.

einpoklum
источник
Связанные с? stackoverflow.com/questions/55950955/…
StoryTeller - Unslander Моника
Per StoryTeller: очевидный дубликат Почему будущая библиотека Ranges не поддерживает инициализацию контейнера из диапазона? - но учтите, что решение по избирательному бюллетеню еще может изменить ответ!
Дэвис Херринг
@DavisHerring Что может измениться? P1206 не рассматривался для 20 с самого начала, и я не думаю, что здесь есть какие-либо комментарии NB? P1391 был принят без конструктора диапазона (несмотря на вводящий в заблуждение пример).
Барри
@Barry: LEWG так переправил его в Kona, но, думаю, я неправильно истолковал недавний трафик отражателей по этому поводу.
Дэвис Херринг
@DavisHerring О, я пропустил, что это обсуждалось дважды - я прокрутил опрос до 4-7 и подумал, что это так.
Барри

Ответы:

8

Мой вопрос: сможем ли мы создать (существующие) контейнеры стандартной библиотеки с любым диапазоном? И что еще важнее, с диапазоном просмотров?

Нет. Единственный стандартный компонент библиотеки, который может быть сконструирован из произвольного диапазона и соответствует правильным критериям std::span<T>.

Скорее всего, в этом направлении будет идти стандартная библиотека, к которой также направляется range-v3 (обратите внимание, что связанный пример из range-v3 компилируется, но предупреждает об устаревшем преобразовании) - используя помощника для выполнения преобразований за вас:

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

Одна из причин не идти в направлении конструкторов диапазона может быть замечена из самого примера, который вы используете:

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

Посмотрите, насколько эта декларация отличается от этих двух:

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

vбудет обязательно vector<transform_view<...>>содержать один transform_view, аw будет vector<int>.

Более того, добавление в стандартную библиотеку дополнительных, тщательно ограниченных конструкторов контейнеров в любом случае не поможет сторонним типам контейнеров - в то время как подобный объект ranges::toработает превосходно во всех случаях.

Барри
источник
Заявления инициализируются vи wвыглядят одинаково для меня. Возможно, вы хотели объявить wкак vector<int>. В противном случае это правильный ответ.
Эрик Ниблер
5
@EricNiebler Точно :-) Они выглядят одинаково. Они не одинаковы.
Барри
Итак, моя программа компилируется, но не будет делать то, что я думаю. Хорошо.
einpoklum
1
Спасибо, CTAD ...
TC
Можете ли вы объяснить, почему vи чем wотличаются? Это как-то связано с тем, как работает вывод аргумента шаблона конструктора?
Йоханнес Шауб - Lit