Можете ли вы объяснить, почему std::ranges::find не работает?

Я озадачен тем, почему, очевидно, невозможно сравнить поддиапазон std::string_view с std::string_view. Я имею в виду, что они должны быть одного и того же базового типа и, следовательно, сопоставимы друг с другом? Может кто-нибудь объяснить, почему это не сработает?

https://godbolt.org/z/3Y6zMaTEv

#include <vector>
#include <string_view>
#include <ranges>
#include <algorithm>

int main() {
    std::vector<std::string_view> forbidden{"123", "4fe", "bad"};
    std::string_view subject = "foo545jdsf4fesub\n55324123434\nsomebadstuff";

    for (auto&& line : subject | std::ranges::views::split('\n')) {
        std::ranges::any_of(forbidden, [&line](auto&& bad) {
            return std::ranges::find(line, bad) != line.end(); // Complains about something being not callable?!
        });
    }
    return 0;
}

Вы имеете в виду диапазоны::поиск?

康桓瑋 30.07.2024 15:17

@康桓瑋 или, возможно, string_view::find?

Caleth 30.07.2024 16:13

@康桓瑋 std::ranges::search по той или иной причине работает, спасибо. Мне бы хотелось понять, почему find не компилируется.

Phoenix 30.07.2024 16:44
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
78
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это потому, что когда вы пытаетесь использовать std::ranges::find(line, bad), строка здесь представляет собой диапазон char, а не std::string_view. Вот почему сравнение не работает должным образом.

Преобразуйте строку в std::string_view с помощью вспомогательной функции и используйте ее std::string_view для выполнения операции поиска.

#include <vector>
#include <string_view>
#include <ranges>
#include <algorithm>
#include <iostream>

std::string_view to_string_view(const std::ranges::range auto& r) {
    auto begin = std::ranges::begin(r);
    auto end = std::ranges::end(r);
    return std::string_view(&*begin, std::ranges::distance(begin, end));
}

int main() {
    std::vector<std::string_view> forbidden{"123", "4fe", "bad"};
    std::string_view subject = "foo545jdsf4fesub\n55324123434\nsomebadstuff";

    for (auto&& line : subject | std::ranges::views::split('\n')) {
        std::string_view line_view = to_string_view(line);

        bool found = std::ranges::any_of(forbidden, [&line_view](auto&& bad) {
            return line_view.find(bad) != std::string_view::npos;
        });

        std::cout << (found ? "Forbidden string found!" : "No forbidden string.") << std::endl;
    }
    return 0;
}

Если вы хотите узнать, содержит ли разделенная подстрока запрещенную подстроку, вы можете просто использовать string_view::contains:

std::vector<std::string_view> forbidden{"123", "4fe", "bad"};
std::string_view subject = "foo545jdsf4fesub\n55324123434\nsomebadstuff";

for (auto line : subject | std::ranges::views::split('\n')) {
  if (std::ranges::any_of(forbidden, [line](auto bad) {
    return std::string_view(line).contains(bad);
  })) {
    // match
  }
}
std::ranges::contains_subrange(line, bad) тоже работает
Caleth 30.07.2024 16:23

@Калет, я думаю, string_view::contains немного более эффективен, поскольку специализируется на строках.

康桓瑋 30.07.2024 16:25
Ответ принят как подходящий

почему, по-видимому, невозможно сравнить поддиапазон std::string_view с std::string_view.

Вы не пытаетесь это сделать. Вы пытаетесь сравнить char с std::string_view. std::ranges::find сравнивает отдельные элементы вида «стог сена» на равенство с «иголкой».

Возможно, вас смутил член std::string_view::find, который выполняет поиск подстроки.

Если вы хотите только узнать, есть ли в строке плохой текст:

for (auto&& line : subject | std::views::split('\n')) {
    std::ranges::any_of(forbidden, [&line](auto bad) {
        return std::ranges::contains_subrange(line, bad);
    });
}

Если вы хотите узнать, где в строке встречается плохое слово:

for (auto&& line : subject | std::views::split('\n')) {
    std::ranges::any_of(forbidden, [&line](auto bad) {
        auto res = std::ranges::search(line, bad);
        // use position of match
        return res.size();
    });
}

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