Поскольку callable
может быть значением xvalue, есть вероятность, что оно будет уничтожено до захвата лямбды, следовательно, вы останетесь с повисшей ссылкой в захвате.Чтобы предотвратить это, если аргумент является r-значением, его необходимо скопировать.
Рабочий пример:
template<class Callable>
auto discardable(Callable&& callable) { // This one makes a copy of the temporary.
return [callable = std::move(callable)]() mutable {
static_cast<void>(static_cast<Callable&&>(callable)());
};
}
template<class Callable>
auto discardable(Callable& callable) {
return [&callable]() mutable {
static_cast<void>(callable());
};
}
Вы все еще можете столкнуться с проблемами времени жизни, если callable
является l-значение ссылки, но его время жизни меньше, чем у лямбда-захвата, возвращаемого discardable
.Таким образом, это может быть самый безопасный и простой способ всегда перемещать или копировать callable
.
В качестве примечания, хотя есть новые специализированные утилиты, которые идеально передают категорию значений объекта функции, например std::apply
, стандартные библиотечные алгоритмы всегда копируют функциональные объекты, принимая их по значению.Так что если кто-то перегружает operator()()&
и operator()()&&
, то стандартная библиотека всегда будет использовать operator()()&
.