0

I am looking for a way to create a binary operation between two predicate functions. This is my predicate function declaration:

template <typename T>
using Predicate = std::function<bool(T const&)>;

I am looking for a way to 'concat' two predicate functions into one:

template <typename T>
static Predicate<T> andPredicate(Predicate<T> a, Predicate<T> b) {
   // ???
}

Expected behaviour:

Predicate<int> a = [](int a) { return a < 5; };
Predicate<int> b = [](int a) { return a > 0; };

Predicate<int> c = andPredicate(a, b); // a < 5 && a > 0

int number = 3;
bool result = c(number);

Is something like this possible in C++?

t4dohx
  • 675
  • 4
  • 24
  • 1
    Why is it static? – Slava May 23 '18 at 18:11
  • You need to return a functionoid that, when called, will itself call `a` and `b` (which it has previously stored) with its own parameter and return the `and` of their results. You're not far ;) – Quentin May 23 '18 at 18:11

2 Answers2

4

Sure, just use a lambda:

template <typename T>
Predicate<T> andPredicate(Predicate<T> a, Predicate<T> b) {
    return [=](T i) { return a(i) && b(i); };
}

You can even avoid the extra overhead of std::function by leveraging templates:

template <typename P1, typename P2>
auto andPredicate(P1&& a, P2&& b) {
    return [a = std::forward<P1>(a), b = std::forward<P2>(b)](const auto& i) {
        return a(i) && b(i);
    };
}

Live Demo

This avoids the extra type-erasure overhead of std::function by accepting the actual types needed for the original predicates and returning the lambda directly. You can then store that in a std::function if you need, or just let the compiler deduce the type with auto.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
0

This should work:

template <typename T>
static Predicate<T> andPredicate(Predicate<T> a, Predicate<T> b) {
   return [a,b]( T const &val ) { return a( val ) and b( val ) };
}

it is not clear why you want to make it static though.

Slava
  • 43,454
  • 1
  • 47
  • 90