Могу ли я использовать split_view с разделителем, который сопоставим, но в остальном не связан с типом значения диапазона разделения?

std::ranges::split_view работает, беря диапазон, который должен быть разделен в паре с разделителем.

Однако указанный разделитель определен довольно своеобразно — он должен быть forward_range.

К счастью, стандарт позволяет использовать split_view таким образом, что передается диапазон и один элемент. Примечательно, что это пример из стандарта:

string str{"the quick brown fox"};

for (auto word : views::split(str, ' ')) {
    cout << string_view(word) << '*';
}

Как видите, мы можем передать ' ' в качестве разделителя. Насколько мне известно, это работает с использованием следующего конструктора:

template<forward_range R>
requires constructible_from<V, views::all_t<R>> 
         && constructible_from<Pattern, single_view<range_value_t<R>>>
constexpr explicit split_view(R&& r, range_value_t<R> e);

Это позволяет нам передавать std::string как диапазон R и char как разделитель e. Предложение requires гарантирует, что это будет работать, проверяя, является ли charrange_value_t для std::string (это так), и возможно ли создать std::ranges::single_view<char> (потенциально всегда делегировать реализацию, которая предполагает, что разделитель является диапазоном). Творит чудеса.

Но что, если я хочу сильно настроить свое поведение разделения? Например, я хотел разбить по любому пробелу. По глупости я думал, что это сработает:

struct Whitespace {
    auto operator==(char const c) const noexcept -> bool {
        return std::isspace(static_cast<unsigned char>(c));
    }

    friend auto operator==(char const c, Whitespace const ws) noexcept -> bool {
        return ws == c;
    }
} whitespace;

auto main() -> int {
    auto const text = std::string("3213 421 43 3 532 5 53 53 5 3535 5353");

    namespace views = std::ranges::views;

    auto numbers = text | views::split(whitespace);
}

Но Whitespace — это тип, который не является диапазоном, из него нельзя создать std::ranges::single_view<char>. И даже если бы это было так и если бы вы могли, у вас не было бы возможности сохранить его пользовательское поведение, учитывая тот факт, что упомянутый конструктор преобразует его в простой, старый char.

Могу ли я как-то использовать std::views::split с пользовательской логикой для разделения, скажем, диапазонов char?

Я думаю, вы хотите что-то более похожее на Range-v3 split_when

TartanLlama 13.04.2023 16:51
Стоит ли изучать 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
1
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Нет. split_view требует indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to>, а ranges::equal_to требует equality_comparable_with (с небольшой оговоркой, здесь не уместной). Семантические требования этой концепции запрещают нетранзитивное «равенство» (т. Е. t1 == u, t2 == u, но t1 != t2), которое необходимо для любого u, которое соответствует более чем одному значению.

Из этого следует, что все попытки сделать такие вещи либо являются IFNDR, либо имеют неопределенное поведение.

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