Реально, вы не можете избежать этого. Вы никогда не знаете, будет ли закрытие вызвано в другой раз; вам нужно будет сохранить значение в случае, если оно есть. Я не буду беспокоиться о выполнении клона, пока профилирование не определит, что это узкое место.
В некоторых случаях вы можете изменить тип закрытия на FnOnce
, что означает, что его можно вызывать только один раз:
fn make_adder<T>(x: T) -> impl FnOnce(T) -> T::Output
where
T: Add,
{
move |y| x + y
}
В других случаях вы можете добавить некоторую косвенность к проблеме. Например, вместо передачи T
, передайте замыкание, которое генерирует T
(предположительно, не путем клонирования собственной захваченной переменной ...). Это T
всегда можно использовать напрямую:
fn make_adder<T>(x: impl Fn() -> T) -> impl Fn(T) -> T::Output
where
T: Add,
{
move |y| x() + y
}