首页 > 解决方案 > 如何使用具有闭包成员的结构创建新的关联函数?

问题描述

我几乎可以直观地理解为什么这段代码不应该工作,但我不能完全理解它。我认为这与新函数每次都有不同的返回类型这一事实有关。

为什么这是个问题?为什么直接创建有效?

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]`

标签: rust

解决方案


tl;博士; 您可以执行以下操作:

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返回 a Struct<T>,而我们在块内声明它里面的所有东西都适用于任何 T令人满意的Fn(&[u8])。但是,您返回的一个特定实例Struct即参数化的实例|msg| {}- 因此,返回值不能是Struct<T>任何令人满意 TFn(&[u8])

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

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

这告诉编译器new返回 a Struct,其参数已知满足Fn(&[u8]),因此编译器应该推断它。特别是它没有关于T并返回一种特定类型的假设。

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

let s = Struct { func: |msg| {} };

编译器看到您想要创建 aStruct并且知道 - 为了创建它 - 它必须推断Tres 的类型。func. 它看到你传递|msg| {}了 for func,推断闭包的类型,现在知道要放入的具体类型T


推荐阅读