Suppose I have the following code that I wish to refactor:
int toFuture()
{
precalc();
int calc = 5 * foobar_x() + 3;
postcalc();
return calc;
}
int toP
I'd say you're refactoring from the wrong side:
struct CalcGuard {
CalcGuard() { /* replaces precalc() */ }
~CalcGuard() { /* replaces postcalc() */ }
};
int toFuture()
{
return CalcGuard(), calc = 5 * foobar_x() + 3;
}
int toPast()
{
return CalcGuard(), calc = 5 * foobar_y() - 9;
}
One approach:
template<typename CalcFuncT>
int perform_calc(CalcFuncT&& calcfunc)
{
precalc();
int const calc = std::forward<CalcFuncT>(calcfunc)();
postcalc();
return calc;
}
int main()
{
perform_calc([]{ return 5 * foobar_x() + 3; }); // toFuture
perform_calc([]{ return 5 * foobar_y() - 9; }); // toPast
}
There is a C/C++
way to do this, and a C++11
way. Neither way involves lambdas or templates.
The C/C++
way:
double MyFunc (int x, float y) { return x + y ; }
int main()
{
double (*pf) (int, float) ;
pf = MyFunc ;
pf (101, 202.0) ;
}
The C++11
way:
#include <functional>
double MyFunc (int x, float y) { return x + y ; }
int main()
{
std::function<double (int, float)> f ;
f = MyFunc ;
f (51, 52.0) ;
}
In either case, you just pass pf
or f
to your refactored function as a parameter. Using lambdas or templates is overkill here.
If you are wanting a template approach using C++11 features, that could look as simple as:
template<typename FuncType>
auto calculation(FuncType&& func) -> decltype(func())
{
precalc();
auto ret = func();
postcalc();
return ret;
}
You would then simply call your calculation
function and pass it either a lambda, a functor, or a function-pointer. Your only souce of difficulty in this instance would be if you passed a function that had a void
return-type ... in that case you will get a compiler error (which is a good thing vs. a runtime error).