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

8

我有以下代码

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(){}

所以User需要一个类型为F1的Helper<F1>,在这种情况下由new_user中的闭包指定。但是,这段代码编译失败,并显示错误消息expected type parameter, found closurenew_user中。据我所知(例如请参阅this link),这是因为在new_user上类型参数F3的限制是由调用者(或签名?)指定的,因此尽管闭包实现了Fn()特征,它将无法限制类型参数F3以匹配闭包的类型。相反,期望new_user能够适用于任何给定的F3,而它显然不会。
那么我的问题是:我该如何解决这个问题?有没有一种表达方式,可以让new_user返回一个User,其中F2设置为闭包的类型?
我尝试使用类型推断占位符:
// error: the type placeholder `_` is not allowed within types on item signatures
fn new_user() -> User<_> {
    User {
        h: Helper { f: || {} },
    }
}

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

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

struct User {
    h: Helper,
}

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

fn main(){}

我也在尝试用自定义特质替换Fn(),这样我就可以为User实现特定的功能,但目前还有些笨拙。

有什么建议吗?

1个回答

9

简而言之:您可能需要这个:

fn new_user() -> User<impl Fn()> {
    User {
        h: Helper { f: || {} },
    }
}

更多细节:让我们深入了解:

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

这意味着new_user“接受”满足Fn()任何内容,但调用者在调用new_user时必须指定。但是为了成功进行类型检查,提供的类型必须与new_user体内使用的类型相同(即 || {} 的类型)。然而,闭包具有匿名类型,因此new_user的调用者无法知道这种类型,因为它无法查看new_user的实现以找出应该为F3提供什么。
如上所述,您希望new_user返回一个User<SomeConcreteType>,其中SomeConcreteType满足F3。调用者不需要 - 实际上甚至不应该 - 指定SomeConcreteType,因为它在new_user内部推断。您可以按以下方式操作:
fn new_user() -> User<impl Fn()> {
    User {
        h: Helper { f: || {} },
    }
}

这样,你可以指定new_user可以在没有参数的情况下被调用,并返回一个满足Fn()的具体类型User


5
你在三天前已经对这个同样的问题进行了回答。请不要鼓励重复提问。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接