以下块是库代码;我无法编辑它:
struct Container<F> {
f: F,
}
fn wrapped<F, T>(f: F) -> Container<F>
where
F: FnMut() -> T,
{
Container { f }
}
我想要专用于T
的包装函数:
fn return_10() -> u32 {
10
}
fn wrapper<F>() -> Container<F>
where
F: FnMut() -> u32,
{
wrapped(return_10)
}
fn main() {
wrapper();
}
(为简单起见,我在上面的代码中使用了u32
,但实际上我想使用特征。我希望这没关系。)
它不起作用:
error[E0308]: mismatched types
--> src/main.rs:20:13
|
20 | wrapped(return_10)
| ^^^^^^^^^ expected type parameter, found fn item
|
= note: expected type `F`
found type `fn() -> u32 {return_10}`
为什么Rust无法推断出T = u32
?我应该不这样做吗?
答案 0 :(得分:4)
当您编写这样的函数签名时:
fn wrapper<F>() -> Container<F>
where
F: FnMut() -> u32;
这意味着:
对于您选择的任何类型
F
,它实现了FnMut() -> u32
,我可以给您一个Container<F>
如果是这种情况,那么您将能够定义一些任意结构,并使其实现FnMut() -> u32
,而wrapper
函数将必须能够以某种方式构想出它的一个实例。 。那将是不可能的-除非FnMut
特性也具有创建新实例的方法。
但是幸运的是,您的代码正在做一些不同的事情。与其为所有可能的类型F
工作,不如只需要它为一种工作,即您知道会返回的一种。
使用impl Trait
来描述的方式:
fn wrapper() -> Container<impl Fn() -> u32> {
wrapped(return_10)
}
这意味着:
我将返回一个
Container<F>
。F
将实现Fn() -> u32
,但是我会选择确切的具体类型。
答案 1 :(得分:1)
我不确定这是否是您要查找的内容,但是此代码可以编译。
struct Container<F> {
f: F,
}
fn wrapped<F, T>(f: F) -> Container<F>
where
F: FnMut() -> T,
{
Container { f }
}
fn return_10() -> u32 {
10
}
fn wrapper() -> Container<fn() -> u32> {
wrapped(return_10)
}
fn main() {
wrapper();
}
我通过使用下面的代码来迫使编译器发出一条消息,告诉我所期望的类型,从而弄清楚了这一点。
struct Container<F> {
f: F,
}
fn wrapped<F, T>(f: F) -> Container<F>
where
F: FnMut() -> T,
{
Container { f }
}
fn return_10() -> u32 {
10
}
fn main() {
let x: () = wrapped(return_10);
}
当您编译上面的代码时,编译器会抱怨
error[E0308]: mismatched types
--> src/main.rs:17:17
|
17 | let x: () = wrapped(return_10);
| ^^^^^^^^^^^^^^^^^^ expected (), found struct `Container`
|
= note: expected type `()`
found type `Container<fn() -> u32 {return_10}>`