Rust 有可能使用trait作为自由函数的语法糖吗?
我想根据外部数据调用函数, 像这样:Rust 有可能使用trait作为自由函数的语法糖吗?,rust,Rust,我想根据外部数据调用函数, 像这样: struct Foo { data: &'static str, handler: Option<fn (i32) -> String>, } fn aaa_converter(_: i32) -> String { unimplemented!(); } fn bbb_converter(_: i32) -> String { unimplemented!(); } fn main() {
struct Foo {
data: &'static str,
handler: Option<fn (i32) -> String>,
}
fn aaa_converter(_: i32) -> String { unimplemented!(); }
fn bbb_converter(_: i32) -> String { unimplemented!(); }
fn main() {
let _ = Foo{data: "aaa", handler: Some(aaa_converter)};
let _ = Foo{data: "bbb", handler: Some(bbb_converter)};
let _ = Foo{data: "ccc", handler: None};
}
trait Handler {
fn handle(a: i32) -> String;
}
impl Handler for "aaa" {
// ...
}
我能找到的最佳匹配是:
trait Handler {
fn handle(/*&self, */a: i32) -> String;
}
struct aaa;
impl Handler for aaa {
fn handle(/*&self, */a: i32) -> String {
unimplemented!();
}
}
struct Foo {
data: &'static str,
handler: &'static Handler,
}
fn main() {}
但这样的代码不会编译:
无法将trait`Handler`制作成对象
=注意:方法“handle”没有接收器
看起来相关,但答案中链接的RFC已过时。也有可能从那以后语言发生了变化
是否可以使用trait作为指向自由函数的简单指针
还是有其他方法来组织处理程序?这里有一个误解:
fn i_am_a_function(a: i32) -> String { a.to_string() }
函子是一个函数对象,它是与某个状态关联的函数。Rust实际上有三种类型:
FnOnce(i32) -> String
FnMut(i32) -> String
Fn(i32) -> String
最后,锈病具有以下特征:
trait Handler {
fn non_object_safe(a: i32) -> String;
fn object_safe(&self, a: i32) -> String;
}
特质可用于两种情况:
- 在泛型函数中提供边界
- 当对象安全时,提供类型擦除
- 没有
或&self
参数&mut self
- 提到
(类型)Self
在您的情况下,您可以使用:
fn(i32)->String
Fn(i32)->String
trait Handler {
fn handle(&self, a: i32) -> String;
}
struct A;
impl Handler for A {
fn handle(&self, a: i32) -> String {
a.to_string()
}
}
const STATIC_A: &'static Handler = &A;
struct Foo {
data: &'static str,
handler: &'static Handler,
}
fn main() {
let foo = Foo { data: "aaa", handler: STATIC_A };
println!("{}", foo.handler.handle(3));
}
如果数据指针的64位开销真的让您烦恼,那么您可以使用函数指针并构建自己的虚拟表:
struct Handler {
handle: fn(i32) -> String,
}
fn aaa(a: i32) -> String {
a.to_string()
}
const STATIC_A: &'static Handler = &Handler { handle: aaa };
struct Foo {
data: &'static str,
handler: &'static Handler,
}
fn main() {
let foo = Foo { data: "aaa", handler: STATIC_A };
println!("{}", (foo.handler.handle)(3));
}
它不太符合人体工程学,但它也小了64位 为什么??为什么不只使用一个空结构,使用
self
参数,而不使用它?@Shepmaster:为什么要使用trait作为开头?;)@马蒂厄姆。我的蜘蛛侠意识告诉我,有时候他们会想要国家。例如,Foo
可能是实际的处理程序,data
应该通过self
@Shepmaster进行访问:公平地说,编译器很难删除数据指针,因为处理程序的一个实现实际上可以完美地使用数据指针。@user1244932:您的问题还很不清楚。从您的评论来看,您似乎希望处理程序
具有多个关联函数;如果是这样的话,它应该反映在问题中!(当你提到许多转换器时,我假设Foo
的一个实例将有一个转换器/函数,因为Handler
有一个函数,而你将有多个Foo
的实例)没有,正如我在问题中指出的,我已经使用了你展示的代码。问题是我有很多这样的函数,比如aaa
,为了组织它们,我需要一些类似traits的东西来简化在代码中找到合适的函数,并向其他人展示应该更新的接口;我建议在本例中使用trait对象,除非您确实有严格的要求,但以防我演示了如何自己构建虚拟表。