I'm trying to find a way to call a number of class member functions, each having differing parameters, with certain known functionality happening before and after the call.
This wrapper function is what I've tried, but for example the final call to it doesn't compile with error:
'bool Wrapper(Work * ,std::function< bool(Args...)>,Args &&...)' : could not deduce template argument for 'std::function< bool(double,std::string,Args...)>' from 'std::_Bind< true,bool,std::_Pmf_wrap< bool (__thiscall Work::* )(double,std::string),bool,Work,double,std::string>,Work *const >'
class Work
{
public:
void DoWork(int a, double b, string c);
private:
void Pre() {};
void Post() {};
bool Step1() { return true; }
bool Step2(int) { return true; }
bool Step3(double, string) { return true; }
};
template<typename... Args>
bool Wrapper(Work *work, std::function<bool(Args...)> func, Args&&... args)
{
work->Pre();
bool ret = func(std::forward<Args>(args)...);
work->Post();
return ret;
}
void Work::DoWork(int a, double b, string c)
{
if (!Wrapper<>(this, std::bind(&Work::Step1, this))) // error
return;
if (!Wrapper<int>(this, std::bind(&Work::Step2, this), a)) // error
return;
if (!Wrapper<double, string>(this, std::bind(&Work::Step3, this), b, c)) // error
return;
}
int main()
{
Work work;
work.DoWork(1, 2.0, "three");
return 0;
}
(Putting the pre- and post- functionality inside the steps would seem at first glance far preferable but that's undesirable as the above is a grossly simplified example of the actual code, and the steps have multiple places of returns, and no tests.)
I thought the explicit template arguments would make the template resolution possible. What am I doing wrong?
With C++11, std::bind
can be replaced by lambda and you can remove template for wrapper :
class Work
{
public:
void DoWork(int a, double b, string c);
private:
void Pre() {};
void Post() {};
bool Step1() { return true; }
bool Step2(int) { return true; }
bool Step3(double, string) { return true; }
friend bool Wrapper(Work *work, std::function<bool()> func);
};
bool Wrapper(Work *work, std::function<bool()> func)
{
work->Pre();
bool ret = func();
work->Post();
return ret;
}
void Work::DoWork(int a, double b, string c)
{
if (!Wrapper(this, [this]() -> bool { return this->Step1(); }))
return;
if (!Wrapper(this, [this, a]() -> bool { return this->Step2(a); }))
return;
if (!Wrapper(this, [this, b, c]() -> bool { return this->Step3(b, c); }))
return;
}
int main()
{
Work work;
work.DoWork(1, 2.0, "three");
return 0;
}
Example : http://coliru.stacked-crooked.com/a/2cd3b3e2a4abfcdc
returned type of std::bind
or lambda are not std::function
and it would be ambiguous which std::function
to construct from them.
One solution is to allow any functor and don't use std::function
template<typename F, typename... Args>
bool Wrapper(Work &work, F&& func, Args&&... args)
{
work.Pre();
const bool ret = std::forward<F>(func)(std::forward<Args>(args)...);
work.Post();
return ret;
}
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With