[英]Missing implementation for top level functions
我试图使一个特质在Rust的顶级函数中可用。
trait FnTrait {
fn call(self);
}
impl FnTrait for fn() {
fn call(self) {
self()
}
}
fn foo() {
println!("Hello, World!")
}
fn main() {
FnTrait::call(foo)
}
但是下面的代码无法使用( Playground Link )进行编译
error[E0277]: the trait bound `fn() {foo}: FnTrait` is not satisfied
--> <anon>:16:5
|
16 | FnTrait::call(foo)
| ^^^^^^^^^^^^^ the trait `FnTrait` is not implemented for `fn() {foo}`
|
= help: the following implementations were found:
<fn() as FnTrait>
= note: required by `FnTrait::call`
我发现我可以像这样通过铸造foo
来欺骗它进行编译
FnTrait::call(foo as fn())
但这很烦人,程序中的某些功能比foo
更复杂。 有什么办法避免演员? 我的特质是错了吗?
Rust中的每个函数都有其自己的类型。 如您所见, foo
不是fn()
,而是fn() {foo}
; 可悲的是,这不是您可以在源代码中编写的实际类型,而只是编译器消息。 存在这种区别是为了使编译器更容易让您将函数作为值传递,同时仍然能够内联调用。
结果是,没有强制转换或类型提示的命名函数指针就不能转换为通用函数指针。 例如,这有效:
fn foo() {
println!("Hello, World!")
}
fn bar(f: fn()) {
f()
}
fn main() {
bar(foo)
}
但是,我不知道有什么方法可以利用它来使特质发挥作用。
前进的唯一方法是停止尝试为函数指针实现trait,而是对所有可调用的对象都实现它:
trait FnTrait {
fn call(self);
}
impl<F> FnTrait for F where F: FnOnce() {
fn call(self) {
self()
}
}
fn foo() {
println!("Hello, World!")
}
fn main() {
foo.call();
}
(有关Fn
, FnMut
和FnOnce
的区别的半相关答案。)
这将适用于该签名可调用的任何内容,包括函数和闭包。 缺点是只能有一个这样的实现。 您不能为任何其他签名实现此特征。
一个通用的实现,或许多特定的实现,以及大量的手动转换。 选择你的毒药。
顺便说一句:Rust中没有“顶级功能”之类的东西,至少与其他类型的功能没有区别。 函数是函数,无论它们出现在何处。 实例函数又称方法仍然是常规函数,只是它们的第一个参数称为“ self”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.