将一个方法从一个项目中借用到另一个拥有它的所有权



我想知道rust是否可以自动将实现Fn(&X) -> Y的函数强制转换为实现Fn(X) -> Y的函数

更具体地说,我有一个具有以下签名的高阶函数:
fn do_stuff<Y, F: Fn(i32) -> Y>(action: F) {
// Does some stuff with the method (specifically, move it into a Box)
}

,我想这样命名它:

do_stuff(i32::to_string)

代替当前

do_stuff(|x| x.to_string())

然而,我得到以下错误:

期望函数签名fn(i32) -> _

发现函数签名for<'r> fn(&'r i32) -> _.

我认为这是因为函数i32::to_string借用了&self作为参数,而闭包则拥有了它的所有权。

是否有办法改变do_stuff的签名,使我也可以这样调用它?


这里是rust游乐场问题的再现。

没有办法将Fn(&T) -> U隐式强制转换为Fn(T) -> U,因为它不属于Rust所允许的隐式强制。但是,有一种方法可以剔除重复代码:

fn add_ref<T, U>(f: impl Fn(&T) -> U) -> impl Fn(T) -> U {
move |ref x| f(x)
}

它适用于(最小化版本)您的示例:

fn do_stuff<Y, F: Fn(i32) -> Y>(_: F) {}
fn main() {
do_stuff(add_ref(i32::to_string))
// do_stuff(i32::to_string)
// ^^^^^^^^^^^^^^^^^^^^^^^^ this would fail
}

看操场

从技术上讲,这是可行的:

use std::borrow::Borrow;
fn do_stuff<X, Y, F: Fn(X) -> Y>(action: F)
where
X: Borrow<i32>,
{
// Does some stuff with the method (specifically, move it into a Box)
}
fn bla(x: i32) {}
fn bla_ref(x: &i32) {}
fn main() {
do_stuff(i32::to_string);
do_stuff(bla);
do_stuff(bla_ref);
}

虽然经常使用|x| x.do_something()闭包是很正常的,所以我不会太担心它。

相关内容

最新更新