0

Is there a C/C++ equivalent structure/class of Predicate class in Java?

Specifically, I have a very simple Java code as given below.

import java.util.function.Predicate;
public class JavaPredicates {
    public static void main(String[] args) {
        Predicate<String> i  = (s)-> s.equals("ABCD");
        Predicate<String> j  = (s)-> s.equals("EFGH");
        Predicate<String> k  = (s)-> s.equals("IJKL");
        Predicate<String> l  = (s)-> s.equals("MNOP");
        Predicate<String> m  = (s)-> s.equals("QRST");
        Predicate<String> n  = (s)-> s.equals("UVWYZ");

        System.out.println(i.or(j).or(k).or(l).or(m).or(n).test("ABCD"));
    }
}

I want to implement the same program in C or C++. Is there a default way or an external library for doing this?

Samet Tonyalı
  • 214
  • 2
  • 9

3 Answers3

4

C++ has lambdas which appear to be quite similar to the java construct you're using:

auto i = [](string const & s){return s == "ABCD";}

It doesn't have the built in chaining, but the concept is similar - an inline-defined function. You can use the C++ logic constructs to combine the lambdas into any construct you'd like -- even use a lambda to do it.

auto final_check = [i,j,k,l,m,n](string const & s){return i(s) || j(s) || k(s).....};
xaxxon
  • 19,189
  • 5
  • 50
  • 80
2

Simplified syntax is auto lambdaName=[ <capture> ] ( <params> ) -> <ret> { body }

  • [<capture>] is the list of Java final vars or effectively finals captured by the lambda, you get to declare them here rather than mark them as final
  • (<params>) is the list of parameters for your lambda
  • ret - returned type - optional if your lambda is simple enough for the compiler to deduce the returned type
  • { body } - self evident

Fully blown explanation on syntax of C++11 lambda functions

In your case:

auto i = [/* no capture */]
          (const std::string& s) // params
          // no ret type spec: simple enough, the compiler will deduce it
          { return s=="ABCD"; }
;
// calling it is just as simple as
std::string str="xyz";
// no more i.test(str), you just call it as a function
bool res0 = i(str); // will be false


const char* charStr="mnp";
bool res1 = i(charStr); // the compiler knows the charStr can be converted
                        // to std::string and will generate the code
                        // for this conversion.
Adrian Colomitchi
  • 3,974
  • 1
  • 14
  • 23
1

For predicates C++ has function object templates that could be used with conjunction with std::bind or lambdas:

auto i = [](auto const& v){ return v == "ABCD"; };
auto j = [](auto const& v){ return v == "EFGH"; };
auto k = bind(equal_to<>{}, "IJKL", placeholders::_1);
auto l = bind(equal_to<>{}, "MNOP", placeholders::_1);

bind is controversial and it's not impossible that it'll be slated for deprecation in future standards, so it's often advisable to use lambdas in its stead.

You can use Boost.Fusion or Boost.Hana to make a similar statement to your chain of ors:

fusion::any(fusion::make_tuple(i, j, k, l), [](auto const& p){ return p("ABCD"); })
hana::any_of(hana::make_tuple(i, j, k, l), [](auto const& p){ return p("ABCD"); })

live: fusion, hana

Alternatively, since C++17 you can use fold expressions for this:

auto const any_of = [](char const* str, auto&&... vs) {
    return (... || vs(str));
};

any_of("ABCD", i, j, k, l)

live demo

Community
  • 1
  • 1
krzaq
  • 16,240
  • 4
  • 46
  • 61