Ответ вслух Senior Лямбды и функциональные объекты обновлено

std::function или шаблон

Вопрос

Как принимать колбэк в функцию или хранить его в классе: std::function, шаблонный параметр, указатель на функцию? Объясните компромиссы.

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Если колбэк нужен только на время вызова функции, я делаю её шаблоном template <std::invocable<int F void each(F&& f): тип известен, вызов встраивается, накладных расходов нет. Минусы: реализация в заголовке и отдельное инстанцирование на каждый тип.

Что должно прозвучать в ответе

  • Шаблонный параметр или `std::invocable`: точный тип, встраивание, но код в заголовке и раздувание

  • std::function: стирание типа, хранение разнородных колбэков, цена аллокации и косвенного вызова

  • Указатель на функцию: дёшево, но без состояния

  • function_ref (C++26) или ссылка на вызываемый для невладеющей передачи

  • move_only_function для move-only замыканий в C++23

Что могут спросить следом

  • Что такое small buffer optimization у std::function?
  • Почему std::function требует копируемости?

Разбор

Если колбэк нужен только на время вызова функции, я делаю её шаблоном template <std::invocable<int> F> void each(F&& f): тип известен, вызов встраивается, накладных расходов нет. Минусы: реализация в заголовке и отдельное инстанцирование на каждый тип. Если колбэк надо хранить в поле класса или в контейнере вместе с другими, нужен единый тип, и тут std::function. Он стирает тип: маленькие замыкания кладёт во внутренний буфер, большие в кучу, вызывает через косвенный переход, который обычно не встраивается, и требует копируемости замыкания. Для move-only замыканий в C++23 есть std::move_only_function. Указатель на функцию самый дешёвый, но не несёт состояния, поэтому годится для лямбд без захватов и C API. В горячих циклах std::function избегаю, а на границах модулей и для подписчиков событий он удобен.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.