Обратный вызов против лямбда
Предположим, у меня есть следующий код, который я хочу реорганизовать:
int toFuture()
{
precalc();
int calc = 5 * foobar_x() + 3;
postcalc();
return calc;
}
int toPast()
{
precalc();
int calc = 5 * foobar_y() - 9;
postcalc();
return calc;
}
В классическом C я бы реорганизовал этот код в employee(), который принимает указатель на функцию, который выполняет вычисление: общий код в worker(), определенный код, предоставляемый указателем функции.
С С++ 11, следует ли вместо этого использовать лямбда? Если да, то как бы реализовать его в этом случае?
Изменить: мне просто пришло в голову, что шаблон также может работать. Как реализация шаблона сравнивается с двумя другими?
Ответы
Ответ 1
Один подход:
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
}
Ответ 2
Если вы хотите использовать шаблонный подход с использованием возможностей С++ 11, это может выглядеть так просто:
template<typename FuncType>
auto calculation(FuncType&& func) -> decltype(func())
{
precalc();
auto ret = func();
postcalc();
return ret;
}
Затем вы просто вызываете свою функцию calculation
и передаете ее либо лямбдой, либо функтором, либо указателем функции. Ваш единственный недостаток сложности в этом случае был бы, если бы вы передали функцию с void
return-type... в этом случае вы получите ошибку компилятора (что является хорошей вещью и ошибкой во время выполнения).
Ответ 3
Я бы сказал, что вы рефакторинг с неправильной стороны:
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;
}
Ответ 4
Существует способ C/C++
сделать это и C++11
. Ни один из способов не включает в себя лямбды или шаблоны.
Способ C/C++
:
double MyFunc (int x, float y) { return x + y ; }
int main()
{
double (*pf) (int, float) ;
pf = MyFunc ;
pf (101, 202.0) ;
}
Способ C++11
:
#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) ;
}
В любом случае вы просто передаете pf
или f
в свою рефакторированную функцию в качестве параметра. Использование lambdas или шаблонов здесь слишком велико.