Generics 为什么';t我的“来自实施的通用”接受框<;Fn()>;价值观

Generics 为什么';t我的“来自实施的通用”接受框<;Fn()>;价值观,generics,rust,type-conversion,closures,traits,Generics,Rust,Type Conversion,Closures,Traits,考虑以下简单结构、该结构的中的实现,以及获取包含装箱函数的结构实例的函数: struct Foo<T>(T); impl<T> From<T> for Foo<T> { fn from(x: T) -> Self { Foo(x) } } fn call(x: Foo<Box<Fn()>>) { let Foo(f) = x; f() } 这无法编译: call(B

考虑以下简单结构、该结构的中的实现,以及获取包含装箱函数的结构实例的函数:

struct Foo<T>(T);

impl<T> From<T> for Foo<T> {
    fn from(x: T) -> Self {
        Foo(x)
    }
}

fn call(x: Foo<Box<Fn()>>) {
    let Foo(f) = x;
    f()
}
这无法编译:

call(Box::new(|| println!("Hello, world!")).into())
call((Box::new(|| println!("Hello, world!")) as Box<Fn()>).into());
给出了以下错误消息:

error[E0277]:不满足特性绑定'Foo:std::convert::From'
-->src/main.rs:15:49
|
15 | call(Box::new(| | println!(“你好,世界!”).into())
|^^^^特性'std::convert::From'未为'Foo'实现`
|
=帮助:找到了以下实现:
=帮助:
=注:由于'std::convert::Into'for'框的impl上的要求,因此需要`

我看不出我的实现中的
Foo
构造函数更严格。为什么
转换成
失败,而
Foo
在这里成功了?

我不确定,但我怀疑这不会发生,因为需要进行两次转换,而且跳数太多。再次签出错误消息:

来自
请注意,该错误提到了一个闭包。在Rust中,每个闭合都是唯一的、不可命名的类型(有时称为a)。闭包是而不是
Fn
,但它确实实现了
Fn

对于从
转换到工作的
,起始类型需要是一个
。我们可以看到,显式转换到
允许它编译:

call(Box::new(|| println!("Hello, world!")).into())
call((Box::new(|| println!("Hello, world!")) as Box<Fn()>).into());
您也可以接受泛型类型:

fn callg<T:Fn()>(x: Foo<Box<T>>) {
    let Foo(f) = x;
    f()
}

fn main() {
    callg(Box::new(|| println!("Hello, world!")).into());
}
fn调用(x:Foo){
设Foo(f)=x;
f()
}
fn main(){
callg(Box::new(| | println!(“你好,世界!”).into();
}

这是因为我们不再转换到
Box
,因此只需要一个转换步骤。

我不确定,但我怀疑这不会发生,因为需要进行两次转换,而且跳数太多。再次签出错误消息:

来自
请注意,该错误提到了一个闭包。在Rust中,每个闭合都是唯一的、不可命名的类型(有时称为a)。闭包是而不是
Fn
,但它确实实现了
Fn

对于从
转换到工作的
,起始类型需要是一个
。我们可以看到,显式转换到
允许它编译:

call(Box::new(|| println!("Hello, world!")).into())
call((Box::new(|| println!("Hello, world!")) as Box<Fn()>).into());
您也可以接受泛型类型:

fn callg<T:Fn()>(x: Foo<Box<T>>) {
    let Foo(f) = x;
    f()
}

fn main() {
    callg(Box::new(|| println!("Hello, world!")).into());
}
fn调用(x:Foo){
设Foo(f)=x;
f()
}
fn main(){
callg(Box::new(| | println!(“你好,世界!”).into();
}

这是因为我们不再转换到
Box
,因此只需要一个转换步骤。

好的,这很有意义,谢谢。但是为什么在我的第一个例子中使用
Foo
函数时不需要
as框呢?如果对任何
t:Fn()
:@ChrisEmerson进行
call
泛型,那么
into
版本也可以工作,但这是不同的。在这种情况下,您不再有
。同意。我现在没有时间详细讨论,但我认为参考资料的内容可能是相关的。我想它说可以直接强制函数参数(第一种情况),而第二种情况不匹配。@ChrisEmerson谢谢,我来看看那个部分!我需要动态调度,而不是静态调度,因为我存储的是一棵树;我的实际类型如下:
enum节点{Branch(HashMap),Leaf(Bar,T)}
OK,这很有意义,谢谢。但是为什么在我的第一个例子中使用
Foo
函数时不需要
as框呢?如果对任何
t:Fn()
:@ChrisEmerson进行
call
泛型,那么
into
版本也可以工作,但这是不同的。在这种情况下,您不再有
。同意。我现在没有时间详细讨论,但我认为参考资料的内容可能是相关的。我想它说可以直接强制函数参数(第一种情况),而第二种情况不匹配。@ChrisEmerson谢谢,我来看看那个部分!我需要动态调度,而不是静态调度,因为我存储的是一棵树;我的实际类型如下:
enum节点{Branch(HashMap),Leaf(Bar,T)}