Это очень ограниченный вариант использования.Для начала, функциональность, присутствующая в локальной функции, должна быть необходима в нескольких точках внутри включающей функции, так что результирующий локальный рефакторинг будет выигрыш в удобочитаемости.В противном случае я напишу встроенную функциональность, возможно, поместив ее в блок, если это поможет.
Но в то же время, функциональность должна быть локальной или достаточно специфичной, чтобы у меня не было стимула для рефакторинга функциональности за пределами (не так) включающей функции, где я мог бы, возможно, повторно использовать ее полностью в другой функции в какой-то момент.Оно также должно быть коротким: в противном случае я просто собираюсь его убрать, возможно, поместив в анонимное пространство имен (или namespace detail
в заголовке) или что-то подобное.Мне не нужно много, чтобы поменять местность в пользу компактности (длинные функции - трудная задача для обзора).
Обратите внимание, что вышесказанное строго не зависит от языка.Я не думаю, что C ++ крутится на этом.Если есть один конкретный совет C ++, который я должен дать по этой теме, это то, что я бы запретил использование захвата по умолчанию по ссылке ([&]
).Не было бы никакого способа определить, описывает ли это конкретное лямбда-выражение замыкание или локальную функцию без тщательного изучения всего тела .Что было бы не так уж плохо (это не значит, что замыкания «страшны»), если бы не тот факт, что эти перехваты ([&]
, [&foo]
) допускают мутации, даже если лямбда не помечена как изменяемая, иЗахваты со значениями ([=]
, [foo]
) могут сделать нежелательную копию или даже попытаться сделать невозможную копию для типов только для перемещения.В общем, я бы предпочел не захватывать что-либо вообще, если это возможно (это то, для чего нужны параметры!), И использовать отдельные захваты при необходимости.Это особенно проблематично
Подводя итог:
// foo is expensive to copy, but ubiquitous enough
// that capturing it rather than passing it as a parameter
// is acceptable
auto const& foo_view = foo;
auto do_quux = [&foo_view](arg_type0 arg0, arg_type1 arg1) -> quux_type
{
auto b = baz(foo_view, arg0, arg1);
b.frobnicate;
return foo_view.quux(b);
};
// use do_quux several times later