Can I use std :: bind to bind state to a function?

I need to pass std :: function to some algorithm. Function type

typedef std::function<bool(const double&)> Condition; 

In the simplest case, this function will look like this:

 bool simpleCondition(const double& d){return d<0.001;} 

Now I want to pass the same condition, but only if the condition is filled several times in a row, the function should return true. I tried the following

 class RepeatingCondition{ public: static Condition getRepeatingCondition(Condition c,int reps){ return std::bind(&RepeatingCondition::evalCondition, RepeatingCondition(c,reps),_1); } private: RepeatingCondition(Condition cc,int reps) : counter(0), reps(reps),cond(cc){} bool evalCondition(const double& d){ if (cond(d)){counter += 1;} else {counter = 0;} return (counter >= reps); } Condition cond; int counter,reps; }; 

My compiler does not complain and seems to work as expected. However, I really don't understand why (with a simple pointer to a function, this will not work, right?). Also, I would like to know if there is an easier way to achieve the same.

+5
source share
2 answers

Is it possible to use std::bind to "attach" a state to a function?

Yes, that’s exactly what. It returns an object (of an undefined class type) containing a pointer to a function and all associated arguments, with a call to operator() to call the function with these arguments.

std::function then encapsulates this object, allowing it to pass and call without knowing its type. This method is known as type erasure.

with a simple function pointer it wont work, right?

Indeed, for this you need something more complex. What std::bind and std::function provide.

In addition, I would like to know if there is an easier way to achieve the same.

Lambda is often more readable than a binding expression:

 static Condition getRepeatingCondition(Condition c,int reps){ RepeatingCondition rep(c,reps); return [rep](double d) mutable {return rep.evalCondition(d);}; } 
+8
source

Since @Mike Seymour has already adopted the lambda approach, I will offer an alternative using functors, which may be a good alternative to the code in the question:

 class RepeatingCondition { Condition m_condition; int m_counter, m_reps; public: RepeatingCondition(Condition c, int reps) : m_condition(c), m_counter(0) , m_reps(reps) { } bool operator()(const double d) { if(m_codition(d)) { m_counter += 1; } else { m_counter = 0; } return (m_counter >= m_reps); } }; 

Now you can create the desired instance using the RepeatingCondition class, for example:

 RepeatingCondition repCond(checkDouble, 12); if(repCond(5.4)) { // calls the operator() overload std::cout << "condition met\n"; } 
+1
source

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


All Articles