如何使用具有闭包成员的结构制作新的关联函数?

时间:2019-01-06 00:27:36

标签: rust

我几乎对为什么这段代码不起作用有一个直观的认识,但是我不能完全依靠它。我认为这与新函数每次都有不同的返回类型有关。

为什么会有问题?为什么直接创建有效?

struct Struct<T>
where
    T: Fn(&[u8]),
{
    func: T,
}

impl<T> Struct<T>
where
    T: Fn(&[u8]),
{
    fn new() -> Struct<T> {
        // this doesn't work
        Struct { func: |msg| {} }
    }
}

fn main() {
    // this works
    let s = Struct { func: |msg| {} };
}

错误是

error[E0308]: mismatched types
  --> src/main.rs:14:24
   |
14 |         Struct { func: |msg| {} }
   |                        ^^^^^^^^ expected type parameter, found closure
   |
   = note: expected type `T`
              found type `[closure@src/main.rs:14:24: 14:32]`

1 个答案:

答案 0 :(得分:4)

tl; dr; ,您可以执行以下操作:

fn new() -> Struct<impl Fn(&[u8])> {
    Struct { func: |msg| {} }
}

更详细:

我们来剖析您的impl区块:

impl<T> Struct<T>
where
    T: Fn(&[u8]),
{
    fn new() -> Struct<T> {
        // this doesn't work
        Struct { func: |msg| {} }
    }
}

我们从开始:

impl<T> Struct<T>
where
    T: Fn(&[u8]),

这告诉编译器,对于满足impl任何 T,整个Fn(&[u8])块都是“有效的”。

现在:

fn new() -> Struct<T> {
    // this doesn't work
    Struct { func: |msg| {} }
}

您说new返回一个Struct<T>,我们在代码块中指出,其中的所有内容均可满足<{> 1 }。但是,您返回{em> T的一个特定实例,即由Fn(&[u8])参数化的一个实例-因此,返回值不能是Struct满足|msg| {}的任何 Struct<T>

但是,您可以对其进行修改以执行以下操作:

T

这告诉编译器Fn(&[u8])返回一个fn new() -> Struct<impl Fn(&[u8])> { Struct { func: |msg| {} } } ,其参数已知满足new,以便编译器应该推断出它。特别是,它没有关于Struct的假设,并返回一种特定类型

但是,在直接初始化中,我们告诉编译器:

Fn(&[u8])

编译器看到您要创建一个T,并且知道为了创建它,它必须推断let s = Struct { func: |msg| {} }; res的类型。 Struct。可以看到您为T传递了func,推断了闭包的类型,现在知道了要放入|msg| {}的具体类型。