C/C++ Эквивалент Java Predicate

Существует ли C/C++ эквивалентная структура / класс класса Predicate в Java?

В частности, у меня есть очень простой код Java, приведенный ниже.

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"));
    }
}

Я хочу реализовать ту же программу на C или C++. Есть ли способ по умолчанию или внешняя библиотека для этого?

3 ответа

Решение

В C++ есть лямбды, которые очень похожи на используемую вами конструкцию java:

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

Он не имеет встроенной цепочки, но концепция похожа - встроенная функция. Вы можете использовать логические конструкции C++ для объединения лямбда-выражений в любую конструкцию, которую вы хотите - даже использовать лямбда-выражения для этого.

auto final_check = [i,j,k,l,m,n](string const & s){return i(s) || j(s) || k(s).....};

Упрощенный синтаксис auto lambdaName=[ <capture> ] ( <params> ) -> <ret> { body }

  • [<capture>] это список Java final vars or effectively finals захваченный лямбда, вы можете объявить их здесь, а не пометить их как final
  • (<params>) список параметров для вашего лямбда
  • ret - возвращаемый тип - необязательный, если ваша лямбда достаточно проста, чтобы компилятор мог вывести возвращаемый тип
  • { body } - самоочевидный

Полностью продуманное объяснение синтаксиса лямбда-функций C++11

В твоем случае:

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.

Для предикатов C++ имеет шаблоны объектов функций, которые можно использовать вместе с std::bind или лямбды:

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 является спорным, и не исключено, что в будущих стандартах он будет объявлен устаревшим, поэтому вместо него часто рекомендуется использовать лямбды.

Вы можете использовать Boost.Fusion или Boost.Hana, чтобы сделать аналогичное утверждение для вашей цепочки 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"); })

жить: фьюжн, хана

В качестве альтернативы, начиная с C++17, вы можете использовать для этого выражения сгиба:

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

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

живое демо

Другие вопросы по тегам