Std :: equal_range with lambda

Let's say I have a row vector, and I want to find all the lines starting with 'a', so I can do this:

struct cmp {
    bool operator()( const std::string &s, char c ) const { return s.front() < c; }
    bool operator()( char c, const std::string &s ) const { return s.front() < c; }
};
std::vector<std::string> strings;
...
std::sort( strings.begin(), strings.end() );
auto range = std::equal_range( strings.begin(), strings.end(), 'a', cmp{} );
...

This method is error prone since it is easy to make a mistake (for example, I think it should be c < s.front()in the second method) and has code duplication.

So, is it possible to implement a comparison function with a common lambda instead of a structure using 2 methods?

The more general question is, why should the value for comparison be passed as an argument std::lower_bound, std::upper_boundand std::equal_rangewhen can it be easily captured by a lambda or passed to the comparison structure, and then this problem will not be there at all?

How could this work if it std::equal_rangedid not require value?

struct cmp {
    cmp( char lc ) : c( lc ) {}
    bool operator()( const std::string &s ) const { return s.front() < c; }
    char c;
};
std::vector<std::string> strings;
...
std::sort( strings.begin(), strings.end() );
auto range = std::equal_range( strings.begin(), strings.end(), cmp{'a'} );
+4
2

lower_bound

std::partition_point(strings.begin(), strings.end(),
                     [](const auto& s) { return s.front() < 'a'; });

upper_bound

std::partition_point(strings.begin(), strings.end(),
                     [](const auto& s) { return s.front() <= 'a'; });

, , , equal_range. :

template<class Iter, class T, class Proj>
std::pair<Iter, Iter> my_equal_range(Iter first, Iter last, const T& value, Proj proj) {
    auto b = std::partition_point(first, last, [&](const auto& s) { return proj(s) < value; });
    auto e = std::partition_point(b, last, [&](const auto& s) { return !(value < proj(s)); });
    return {b, e};
}

my_equal_range(strings.begin(), strings.end(), 'a',
               [](const auto& s) { return s.front(); });

Ranges TS , ( ) :

std::experimental::ranges::equal_range(strings, 'a', {},
                                       [](const auto& s) { return s.front(); });
+4

, , , . , char string.

auto get_char(char c)               { return c; }
auto get_char(std::string const& s) { return s.front(); }
auto cmp = [](auto const& l, auto const& r) { return get_char(l) < get_char(r); };


, , , equal_range , - (, ), .

+4

Source: https://habr.com/ru/post/1613765/


All Articles