Как в C++ std::ranges построить карту на основе результата view::join?

Я использую GCC 14 в режиме C+23. В следующем коде я создаю представление представлений пар, которое затем выравниваю с помощью view::join и помещаю в вектор:

auto c = std::ranges::views::iota(1, 5)
        | std::ranges::views::transform([](int const v){
                return std::ranges::views::iota(1, 3)
                    | std::ranges::views::transform([v](int const w){
                            return std::make_pair(v, std::format("[{}/{}]", v, w));
                    });
        })
        | std::ranges::views::join
        | std::ranges::to<std::vector>();

Результатом является вектор пар.

Теперь вместо вектора пар я хотел бы создать карту (или unordered_map). Построение карты из ряда пар должно работать (, как я узнал из своего старого вопроса ). Но здесь это не компилируется:

auto c = std::ranges::views::iota(1, 5)
        | std::ranges::views::transform([](int const v){
                return std::ranges::views::iota(1, 3)
                    | std::ranges::views::transform([v](int const w){
                            return std::make_pair(v, std::format("[{}/{}]", v, w));
                    });
        })
        | std::ranges::views::join
        | std::ranges::to<std::map>();

К сожалению, вывод компилятора мне не совсем понятен. Все, что я получил от него, это то, что он не может вызвать std::construct_at для создания узла карты, но я не могу многого понять из всех внутренних устройств стандартной библиотеки.

Использование только одного уровня «вложенных» диапазонов работает как положено. Таким образом, эта проблема возникает только тогда, когда вложенные уровни диапазона объединяются и преобразуются в карту.

Как заставить второй код компилироваться и работать как положено?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
112
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

libstdc++ в настоящее время не реализует диапазонную версию конструктора map, а именно map(std::from_range_t, R&&), и поскольку создаваемый вами объединенный диапазон не является common_range, ranges::to отправит маркер (2.1.4) для первого построения по умолчанию map, а затем поместите элементы в map через c.emplace(c.end(), *it).

Обратите внимание, что чаще всего ожидается вызов emplace() контейнера последовательности, такого как vector, а не map, поскольку emplace() последнего не обязательно принимает итератор в качестве первого аргумента. Однако, поскольку map::emplace() является неограниченной функцией, она все равно вызывается и вызывает серьезную ошибку.

Обходной путь — использовать views::common для преобразования объединенного диапазона в common_range, чтобы map можно было создать с помощью классического конструктора map(InputIt first, InputIt last).

auto c = std::views::iota(1, 5)
        | std::views::transform([](int const v){
                return std::views::iota(1, 3)
                    | std::views::transform([v](int const w){
                            return std::make_pair(v, std::format("[{}/{}]", v, w));
                    });
        })
        | std::views::join
        | std::views::common // no need for libc++
        | std::ranges::to<std::map>();

Демо

common это был деликатный вопрос 👍🏻
Red.Wave 15.07.2024 18:34

Другие вопросы по теме