如何专门化函数的返回值?

时间:2018-07-10 18:09:11

标签: generics rust

以下块是库代码;我无法编辑它:

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?我应该不这样做吗?

2 个答案:

答案 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}>`