В общем поэтому такие замыкания в C++ не очень часто используют, разве что очень примитивные без std::function которые гарантированно всплывут и заинлайнятся. Помню в Binaryen была проблема с производительностью когда кто-то отрефакторил код и заменил обычный указатель на функцию на std::function =)
Компилятор может заинлайнить только те замыкания которые всплывут (lambda lifting). Хотя я даже не уверен что LLVM поддерживает такой вид трансвормации
Иными словами все свободные переменные (немутирующие) попадают в сигнатуру в качестве параметра. И все вызовы (call sites) так же модифицируются соответствующим образом. В конечном итоге мы полностью избавляемся от замыкания
А как тут понять что происходит? Хотелось бы все же выяснить как эта проблема решается во взрослых языках и компиляторах где есть замыкания потому что я вижу в этом большую проблему - если функция вызывается в горячем цикле а внутри создается замыкание под if-ом который срабатывает очень редко то с простым боксингом замыкаемых переменных мы получаем падение производительности на каждой итерации даже когда замыкания не создаются