为啥我可以在结构的类型参数中编写函数类型?
Posted
技术标签:
【中文标题】为啥我可以在结构的类型参数中编写函数类型?【英文标题】:Why am I able to write a function type in the type parameter of a struct?为什么我可以在结构的类型参数中编写函数类型? 【发布时间】:2021-12-25 06:40:42 【问题描述】:如果我理解正确的话,在 Rust 中,每个闭包类型都有一个无法写出的唯一类型。我也认为这适用于函数,但是,我可以执行以下操作,其中我在 get_struct_1
和 get_struct_2
的返回类型中显式编写类型参数:
struct FooStruct<F>
where F: Fn(i32) -> i32
f: F,
fn foo(x: i32) -> i32
2*x
fn bar(x: i32) -> i32
-1*x
fn get_struct_1() -> FooStruct<fn(i32) -> i32>
FooStruct f: foo
fn get_struct_2() -> FooStruct<fn(i32) -> i32>
FooStruct f: bar
// This does not work - the trait has to be boxed
//fn get_struct_3() -> FooStruct<Fn(i32) -> i32>
//
// FooStruct f: |x| 10*x
//
fn main()
let mut x = get_struct_1();
// Why does this work - do bar and foo have the same type?
x = get_struct_2();
// Why does this work - doesn't a closure have its own unique, unwriteable type?
x = FooStruct f: |x| 10*x ;
let mut y = FooStruct f: |x| 10*x ;
// Does not work - no two closures have the same type.
//y = FooStruct f: |x| 10*x ;
// Does not work - even though the 'other way around' worked with x.
// But _does_ work if I type-annotate y with FooStruct<fn(i32) -> i32>
//y = get_struct_1();
我认为 Rust 在处理类型参数的方式上是单态的。所以如果我这样做
struct FooStruct
f: Box<dyn Fn(i32) -> i32>
程序会在运行时动态确定运行哪个f
,但FooStruct<F>
版本避免了动态调度。
这个例子似乎不同意这一点。如果x = get_struct_2();
行位于if
语句中,编译器将无法确定x
是否持有函数foo
或bar
的包装版本。
【问题讨论】:
【参考方案1】:闭包(以及与此相关的函数)确实具有独特的、不可写的类型。但是,当它们不捕获任何变量时,它们也可以(并且也隐式地*)转换为函数指针,而您的却没有。这基本上是它起作用的原因:
fn main()
// closure is inferred to be a function pointer
let mut f: fn() -> i32 = || 5;
// assigning a different function pointer
f = || 6;
但这不是:
fn main()
// closure is inferred to be a unique closure type
let mut f = || 5;
// uh oh! different closure type, errors
f = || 6;
* 与其说是隐式转换,不如说是隐式类型推断
【讨论】:
好的,这很有帮助。但这是否意味着在您的第一个示例中,动态调度是在调用f
时发生的?
并非如此。 f
存储一个指向函数的指针,当您调用 f
时,它指向的任何内容都会被调用。你可以说它是动态调度,f
指向的东西可以改变,但不涉及 vtables,就像处理dyn Trait
时一样以上是关于为啥我可以在结构的类型参数中编写函数类型?的主要内容,如果未能解决你的问题,请参考以下文章