Can I create a predicate that will take both functions and functors as a parameter?

I am working on a problem in C ++ that involves many subset and conversion operations for large amounts of data. To this end, I created a map function and a sort of list comprehension. I found that the bunch of predicates that I write also has inversions, so I need to write:

template <typename type_t>
bool HasTenFoo(const type_t &t) {
  return t.foo >= 10.0;
}

and

template <typename type_t>
bool DoesntHaveTenFoo(const type_t &t) {
  return t.foo < 10.0;
}

None of them are real examples, but they are representative. I also use a large number of functors, such as:

class HasEnoughFoo {
public:
  HasEnoughFoo (double bar) { this->bar = bar; }
  template<typename type_t>
  bool operator()(const type_t &t) const { return t.foo >= bar; }
private:
  double bar;
};

some of them must also have inverse. Instead of duplicating the code unnecessarily, I would like to write a functor that takes a predicate as an argument and returns (value) the opposite of that predicate. My fist, one below:

/* -- Returns the opposite of some other predicate -------------------------- */

template<typename predicate_t>
class Not {
public:
  template <typename predicate_t>
  Not(predicate_t *p) { predicate = p; }

  template <typename type_t>
  bool operator()(const type_t &t) const {
    return !(*predicate)(t);
  }

private:
  predicate_t *predicate;
};

I would call it something like:

new_list = old_list.subset(Not<HasEnoughFoo>(&HasEnoughFoo(10.0));

or

new_list = old_list.subset(Not<HasTenFoo>(&HasTenFoo));

, , predicate_t HasEnoughFoo, , predicate_t HasTenFoo.

Visual Studio , 'HasTenFoo' is not a valid template type argument for parameter 'predicate_t'. Not(), , ?

+3
6

, ( foo, ).

template <typename type_t>
bool HasTenFoo(const type_t &t) {
  return t >= 10.0;
}

class HasEnoughFoo {
public:
  HasEnoughFoo (double bar) { this->bar = bar; }
  template<typename type_t>
  bool operator()(const type_t &t) const { return t >= bar; }
private:
  double bar;
};


template<typename predicate_t>
class Not {
public:
  Not(predicate_t p): predicate(p) { }

  template <typename type_t>
  bool operator()(const type_t &t) const {
    return !predicate(t);
  }

private:
  predicate_t predicate;
};

template <class predicate_type>
Not<predicate_type> Negate(predicate_type p)
{
    return p;
}

#include <iostream>
int main()
{
    std::cout << Negate(HasTenFoo<double>)(11.0) << '\n';
    std::cout << Negate(HasEnoughFoo(13.0))(11.0) << '\n';
}

:

. , ( hasEnoughFoo ).

. , .

Not , ( , ), , ( ) - Negate.

+5

.

, HasTenFoo . ; , . . &HasTenFoo , &HasTenFoo<Bar> . HasTenFoo<Bar> HasTenFoo.

, Not , . HasTenFoo<Bar>, bool(*)(const Bar&).

,

Not<bool(*)(const Bar&)>(&HasTenFoo<Bar>)

, , /, . ; , , .

+3

not1 . . , unary_predicate. .

ptr_fun , .

, - (, , , )

int factorial (int x) {
    ....
}
std::transform (d.begin (), d.end (), v.begin (), std::ptr_fun (factorial));
std::transform (d.begin (), d.end (), v.begin (), not1(std::ptr_fun (factorial)));
+3
0

. . , . . , , , operator(), .operator(), . , . .

template<typename type_t> class HasEnoughFoo {
public:
  HasEnoughFoo (double bar) { this->bar = bar; }
  bool operator()(const type_t &t) const { return t.foo >= bar; }
private:
  double bar;
};

template<typename predicate_t, typename type_t>
class Not {
public:
  Not(const predicate_t& p) { predicate = p; }

  bool operator()(const type_t &t) const {
    return !(predicate(t));
  }

private:
  predicate_t predicate;
};

, .

typedef type_t MyCustomType;
new_list = old_list.subset(Not<HasEnoughFoo<type_t>>(&HasEnoughFoo<type_t>(10.0));
new_list = old_list.subset(Not<decltype(HasTenFoo<&type_t)>>(&HasTenFoo<type_t>));

:
, .
, - , ?

, decltype, , . .

0

, , , Not .

-, Not - - template .

template<typename predicate_t>
class Not {
public:
  Not(predicate_t *p) { predicate = p; }

  template <typename type_t>
  bool operator()(const type_t &t) const {
    return !(*predicate)(t);
  }

private:
  predicate_t *predicate;
};

template, . , . , , .

, HasTenFoo,

new_list = old_list.subset(Not<bool(const LIST_ELEMENT&)>(&HasTenFoo));

,

typedef bool OrdinaryFuncPredicate(const LIST_ELEMENT&);
new_list = old_list.subset(Not<OrdinaryFuncPredicate>(&HasTenFoo));

, Not. , , ( , , , ). , . . , , LIST_ELEMENT .

0

Source: https://habr.com/ru/post/1758226/


All Articles