lightalex
@lightalex

Как передать лямбду-функцию по ссылке, а затем присвоить в переменную?

Добрый вечер
Есть функция которая сохраняет передаваемую через параметры лямбду-функцию в глобальную переменную:
typedef void(*callbackType) (int);

callbackType globalCallback;

void setit(callbackType callback) {
	globalCallback = callback;
}

int main() {
	int localVar = 5;
	setit([](int num) {
		std::cout << num;
		// std::cout << localVar;
	});
}

Но мне нужно видеть в лямбде-функции переменную localVar
То есть вызывать setit([&](int num) { ... } , а потом каким-то образом присваивать лямбду-функцию в globalCallback
Пробовал сделать через functional
Не получилось присвоить в globalCallback + пишут что functional тяжелый класс и его лучше не использовать
Посему решил обратиться за советом и помощью к знающим людям
Заранее благодарю за ответы!
  • Вопрос задан
  • 513 просмотров
Решения вопроса 1
@Ariox41
Для начала, сохранять функцию обратного вызова в глобальной переменной - уже плохая идея. Иногда имеет смысл сохранять 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 - в худшем случае она работает в два раза медленнее, чем обычные виртуальные функции. Можно написать свою реализацию специально для лямбд, которая будет работать чуть быстрее за счет меньшей универсальности, но принципиально ситуацию это не меняет - в большинстве случаев это незначительные расходы. Если всё же нужно оптимизировать - нужно менять архитектуру программы, передавать лямбды в качестве шаблонных параметров непосредственно к месту вызова, если это возможно (тогда они инлайнятся), использовать те же виртуальные функции и классические механизмы ООП.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы