1

Does Boost Hana provide a way to combine predicates with logical operators?

I'm referring to something roughly like this

constexpr auto both = [](auto&& f, auto&& g){
    return [&f,&g](auto&& x){ return f(x) && g(x); };
};

that could be used like this:

int main() {
    std::vector<int> v{1,2,3,4,5,6,7,8,9,10};
    auto less_than_7 = hana::reverse_partial(std::less_equal<int>{}, 7);
    auto more_than_3 = hana::reverse_partial(std::greater_equal<int>{}, 3);
    auto r = ranges::views::remove_if(v, both(less_than_7, more_than_3));
}

where, from Hana, I'd expect also a way to use it in an infix way similar to hana::on, as in both(less_than_7, more_than_3) === less_than_7 ^both^ more_than_3 (even though and would be nicer, but I've just found that it's a synonym for &&).

Or maybe does it offer a way to lift the standard operator && to operate on function functors?

Enlico
  • 23,259
  • 6
  • 48
  • 102

1 Answers1

2

You could use demux like:

auto both = hana::demux(std::logical_and<bool>{});
// Or for any number of predicates
auto all = hana::demux([](auto const&... x) noexcept(noexcept((static_cast<bool>(x), ...))) { return (true && ... && static_cast<bool>(x)); });
ranges::views::remove_if(v, both(less_than_7, more_than_3));
Artyer
  • 31,034
  • 3
  • 47
  • 75
  • Oh, great! The name `all` is a bit misleading, as it conveys imho that it will `and`/`&&` together the result of _zero or more_ predicates, rather than two. I would reserve that name to `hana::demux([](auto const&... x){ return (... && x); })`. If you're fine with it, I can edit your answer myself, if not, I can add another answer for the readers (yours stays accepted). – Enlico Oct 08 '20 at 13:20
  • 1
    @Enrico For some reason I thought `logical_and` was variadic. Fixed it now though – Artyer Oct 08 '20 at 14:40
  • Oh, what is all that? Could you explain a bit why `noexcept(bla)` (which I guess has no relevance as for what the function does) and `true && ... &&`, which I suspect has to do with calling the function `all` with zero args, which does not seem to work anyway. – Enlico Oct 08 '20 at 14:49
  • 1
    @Enrico `noexcept(...)` just makes the lambda noexcept if all the arguments can be `noexcept`-converted to bool (allows for some optimisations). `true && ... &&` is redundant, but I find it more clear (there's an edge case for `... &&` making it `true` for an empty pack). And `all()(x) == true` (makes sense as "all 0 constraints are satisfied") – Artyer Oct 08 '20 at 15:46