错误:预期类型参数,发现闭包

Ale*_*ing 4 generics traits rust

我有以下代码

struct Helper<F1: Fn()> {
    f: F1,
}

struct User<F2: Fn()> {
    h: Helper<F2>,
}

fn new_user<F3: Fn()>() -> User<F3> {
    User {
        // error: expected type parameter, found closure
        h: Helper { f: || {} },
    }
}

fn main(){}
Run Code Online (Sandbox Code Playgroud)

所以User需要一个Helper<F1>由 指定的 F1 类型User,在这种情况下是由中的闭包new_user

此代码编译失败与错误expected type parameter, found closurenew_user。至于我已经明白(例如见这个链接),这是因为约束类型参数F3new_user被调用者指定(或签名也许?),因此,虽然关闭实现Fn()特质,它不能限制类型参数 F3 以匹配闭包的类型。相反,它new_user应该适用于任何给定的F3,而这显然不会。

所以我的问题是:我该如何解决这个问题?有没有表达,我想的任何方式new_user返回一个UserF2 set到闭包的类型吗?

我尝试使用类型推断占位符:

// error: the type placeholder `_` is not allowed within types on item signatures
fn new_user() -> User<_> {
    User {
        h: Helper { f: || {} },
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以使用 Box,但这需要修改Helper,这在我的实际情况中并不理想:

struct Helper {
    f: Box<dyn Fn()>,
}

struct User {
    h: Helper,
}

fn new_user() -> User {
    User {
        h: Helper { f: Box::new(|| {}) },
    }
}

fn main(){}
Run Code Online (Sandbox Code Playgroud)

我也在尝试Fn()用自定义特征替换,我可以User专门实现它,但到目前为止它很笨重。

有什么建议?

phi*_*mue 6

tl;博士; 你可能想要这个:

fn new_user() -> User<impl Fn()> {
    User {
        h: Helper { f: || {} },
    }
}
Run Code Online (Sandbox Code Playgroud)

更多细节:让我们看看这个:

fn new_user<F3: Fn()>() -> User<F3> {
    User {
        // error: expected type parameter, found closure
        h: Helper { f: || {} },
    }
}
Run Code Online (Sandbox Code Playgroud)

这表明new_user“接受”任何令人满意的Fn(),但调用者在调用 时必须指定它new_user。但是,要成功进行类型检查,提供的类型必须与 , 主体中使用new_user的类型(即 的类型|| {})相同。但是,闭包具有匿名类型,因此 的调用者new_user无法知道这种类型,因为它无法查看new_usertoo的实现以找出为 提供什么F3

如前所述,您想要的是new_user返回一个User<SomeConcreteType>where SomeConcreteTypesatisfies F3。调用者不需要——事实上它甚至不应该——指定SomeConcreteType,因为它是在new_user. 您可以按如下方式执行此操作:

fn new_user() -> User<impl Fn()> {
    User {
        h: Helper { f: || {} },
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您指定new_user可以在没有任何参数的情况下调用,并且它返回User具有满足Fn().

  • [你真的在 3 天前回答了这个 *相同的问题 *](/sf/answers/3784265061/)。**请不要鼓励重复**。 (5认同)