gpt4 book ai didi

rust - 为动态 Fns 实现特征

转载 作者:行者123 更新时间:2023-12-03 11:28:24 27 4
gpt4 key购买 nike

今天我在研究函数特征。尽管我在下面展示的示例实际上可能不是很有用,但我确实想知道为什么它无法编译。

pub fn do_something(o: &(dyn Other + 'static)) {

}

trait Other {
fn do_something_other(&self);
}

impl<A> Other for dyn Fn(A) {
fn do_something_other(&self) {
do_something(self);
}
}

在这里,我为函数类型实现了一个特征。此函数类型在其参数上是通用的。这意味着如果您这样做:

pub fn do_something(o: &(dyn Other + 'static)) {

}

trait Other {
fn do_something_other(&self);
}

impl<F, A> Other for F where F: (Fn(A)) + 'static {
fn do_something_other(&self) {
do_something(self);
}
}

您收到一条错误消息,指出类型参数不受约束。 error1

我明白这一点,但不相信用泛型可以做到这一点。但是动态的方式,为什么不行呢?它给出了以下错误:

error2

我不明白这个错误。它声明我传递了一个 Fn(A) -> (),它没有实现 Other。但是,此错误确实发生在 Other 的实现中。怎么不能在这里实现呢?

我的第一个想法是因为每个闭包都是它自己的类型。如果它与此有关,我发现错误很奇怪。

最佳答案

第一个构造失败,因为您无法转换 &dyn A进入&dyn B , 即使在实现 B 时对于 dyn A .

trait A {}

trait B {
fn do_thing(&self);
}

impl B for dyn A {
fn do_thing(&self) {
let b: &dyn B = self;
}
}
error[E0308]: mismatched types
--> src/lib.rs:9:25
|
9 | let b: &dyn B = self;
| ------ ^^^^ expected trait `B`, found trait `A`
| |
| expected due to this
|
= note: expected reference `&dyn B`
found reference `&(dyn A + 'static)`

好吧,您可以转换特征,但只能在源特征的帮助下进行。但由于在这种情况下来源是 Fn ,那不是一条路线。


第二个构造失败,因为 Rust 不允许您实现可能发生冲突的特征。试图实现 B对于实现 A<_> 的类型将被自动拒绝,因为类型可以有多个 A<_> 的实现.

trait A<T> {}

trait B {
fn do_thing(&self);
}

impl<T, U> B for T where T: A<U> {
fn do_thing(&self) {}
}
error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:7:9
|
7 | impl<T, U> B for T where T: A<U> {
| ^ unconstrained type parameter

关于 Fn特别是,它有点难以分辨,因为通常函数对象只实现一个 Fn。特征。但是,关键字是通常,因为您可以在每晚启用一项功能来做到这一点。而且特质系统通常不会播放收藏夹。


那你能做什么?好吧,第一个方法仍然功能性,只是您必须将实现保持在特征范围内。如果您对函数参数使用具体类型,则可以使用第二种方法。

你可以想像地实现 Other对于 &dyn Fn(_) (在引用而不是对象本身上实现它)。但这并不是特别方便 Fn通常使用对象。

pub fn do_something(o: &dyn Other) {}

trait Other {
fn do_something_other(&self);
}

impl<A> Other for &dyn Fn(A) {
fn do_something_other(&self) {
do_something(self);
}
}

fn main() {
// THIS WORKS
let closure: &dyn Fn(_) = &|x: i32| println!("x: {}", x);
closure.do_something_other();

// THIS DOESN'T WORK
// let closure = |x: i32| println!("x: {}", x);
// closure.do_something_other();
}

另一种选择是制作 Other trait generic 为了约束A ,但这当然取决于它的设计用途。

关于rust - 为动态 Fns 实现特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66305832/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com