Question

Count matching elements after splitting

I want to combine std::views::split or std::views::lazy_split with std::ranges::count but I cannot get it to work.

This is what I currently have:

std::string setting;
std::string extension;

const auto count = std::range::count(setting | std::views::split(' '), extension);

And unfortunately the MSVC error is not really helpful:

error C3889: call to object of class type 'std::ranges::_Count_fn': no matching call operator found

How can I count the elements that match extension after splitting (without having to store the parts into a container)?

 3  90  3
1 Jan 1970

Solution

 4

The subranges after the split cannot be compared with string, so the constraint is not satisfied.

You can use the projection to project them into string_views, which makes them comparable to strings:

std::string setting;
std::string extension;

const auto count = std::ranges::count(
    setting | std::views::split(' '), 
    extension,
    [](auto r) { return std::string_view(r.data(), r.size()); }
);

Or with views::transform:

const auto count = std::ranges::count(
    setting | std::views::split(' ')
            | std::views::transform(
                [](auto r) { return std::string_view(r.data(), r.size()); }),
    extension
);
2024-07-11
康桓瑋

Solution

 0

std::string and std::string_view are not currently equality comparable to range::split_view or ragne::lazy_split_view elements. I would go for count_if with equal perdicate:

const auto count = std::range::count_if
                 ( setting
                 | std::views::split(' ')
                 , std::bind_front( std::ranges::equal
                                  , std::cref(extension) )
);

All C++20, no iterators or explicit loops. A more strict approach would use std::string::compare as perdicate:

const auto count = std::range::count_if
                 ( setting
                 | std::views::split(' ')
                 , [&extension](auto const& r)
                 { return not extension.compare(r); }
);
2024-07-11
Red.Wave