4

In the below example a struct Comp is created. Is there a way to make it a std::function or write the comparator itself while calling std::equal_range? Can I get rid of the struct?

struct Comp
{
    bool operator() ( const S& s, int i ) const { return s.number < i; }
    bool operator() ( int i, const S& s ) const { return i < s.number; }
};
     
const auto p2 = std::equal_range(vec.begin(),vec.end(), 2, Comp{});
Enlico
  • 23,259
  • 6
  • 48
  • 102
abhijit jagdale
  • 609
  • 2
  • 8
  • 21

2 Answers2

3

You can use boost::hana::overload to overload lambdas:

    auto constexpr comp = boost::hana::overload(
        []( const S& s, int i ) { return s.number < i; },
        []( int i, const S& s ) { return i < s.number; }
    );

    const auto p2 = std::equal_range(vec.begin(),vec.end(), 2, comp);

Obviously you can put the whole boost::hana::overload(…) thing in the call to std::equal_range, but it just makes the code less readable, imho.

However, I would stress that whether you write it yourself or not, you'll likely end up with using a struct/class; e.g. std::function is a templated class, boost::hana::overload is an object of a given class, and so on.

Since you haven't specified a standard, probably using Jeff Garrett solution is the way to go (though I'd change vec.begin(), vec.end(), to vec,, if you are to process the whole vec). If you have to be C++17 compliant, than you can use Range-v3:

#include <range/v3/algorithm/equal_range.hpp>
// ...
const auto p2 = ranges::equal_range(vec, 2, std::less{},
    [](const S& s) { return s.number; });

which is ok for C++14 too, as long as you don't rely on CTAD:

const auto p2 = ranges::equal_range(vec, 2, std::less<>{},
    [](const S& s) { return s.number; });
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • I guess a lambda taking `auto&&` and a ladder of `if constexpr` checking type traits should also work? Not that I would consider it particularly good coding style, but for the sake of completeness I guess might also be worth mentioning. – alagner Mar 24 '21 at 09:35
  • @alagner, I'm not sure I've understood what you refer too. Probably you should post an answer. Notice that you can pass generic lambdas to `boost::hana::overload`, so you can also have a catch-all lambda... – Enlico Mar 24 '21 at 09:38
1

The ranges versions support projections:

std::ranges::equal_range(vec.begin(), vec.end(), 2, std::less{},
    [](const S& s) { return s.number; });
Jeff Garrett
  • 5,863
  • 1
  • 13
  • 12