Для начала, сохранять функцию обратного вызова в глобальной переменной - уже плохая идея. Иногда имеет смысл сохранять call back в неизменной статической переменной, например, для ручной реализации таблицы виртуальных функций:
static constexpr std::array<callbackType, n>
Но к этому нужно подходить с осторожностью. Возможно, в глобальную (лучше - в статическую) переменную нужно сохранять не функцию, а как раз переменные, которые нужно захватить.
Но если всё же хотите, должен сработать такой вариант:
template<class Rt, class Fn>
Rt static_capture(Fn fn){
static Fn state = std::move(fn);
return []{
state();
};
}
int main() {
int localVar = 5;
setit(static_capture<callbackType>([localVar](int num) {
std::cout << num;
std::cout << localVar;
}));
}
Тут для каждой лямбды будет своя конкретизация шаблона и, соответственно, своя статическая переменная.
Что касается
std::function
- в худшем случае она работает в два раза медленнее, чем обычные виртуальные функции. Можно написать свою реализацию специально для лямбд, которая будет работать чуть быстрее за счет меньшей универсальности, но принципиально ситуацию это не меняет - в большинстве случаев это незначительные расходы. Если всё же нужно оптимизировать - нужно менять архитектуру программы, передавать лямбды в качестве шаблонных параметров непосредственно к месту вызова, если это возможно (тогда они инлайнятся), использовать те же виртуальные функции и классические механизмы ООП.