#![feature(unboxed_closures)]
#![feature(fn_traits)]
struct foo;
impl std::ops::Add for foo {
type Output = foo;
fn add(self, x: foo) -> foo {
println!("Add for foo");
x
}
}
impl Fn for foo {
extern "rust-call" fn call(&self) -> Self {
println!("Call for Foo ");
self
}
}
fn main() {
let x = foo;
let y = foo;
x + y;
x();
}
我实现了Add
特征,但我不明白如何将结构作为函数调用。我收到错误:
error[E0243]: wrong number of type arguments: expected 1, found 0
--> src/main.rs:14:10
|
14 | impl Fn for foo {
| ^^ expected 1 type argument
我是Rust的新手,无法找到如何使这件事发生的例子。
答案 0 :(得分:14)
你还不能在稳定的Rust中实现Fn*
特征。这只适用于使用#[feature]
的夜间编译器!
完全阅读您正在实施的特征以了解如何实现它非常有用。 Fn
trait定义为:
pub trait Fn<Args>: FnMut<Args> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
请注意实现和定义之间的任何差异?我看到很多:
实施没有为Args
提供价值!这就是编译器指向的内容。另请参阅Wrong number of type arguments: expected 1 but found 0
实现并没有实现supertrait FnMut
,它本身需要supertrait FnOnce
。 FnOnce
是声明关联类型 Output
的地方。
实现忽略了定义具体类型Output
应该是什么。
当特征返回Self
时,实现返回Self::Output
。
实施不接受call
的第二个参数。该参数包含传入的任何参数。
此外,Rust中的类型使用PascalCase
,而不是snake_case
,因此它应为Foo
。
#![feature(unboxed_closures)]
#![feature(fn_traits)]
struct Foo;
impl Fn<()> for Foo {
extern "rust-call" fn call(&self, _args: ()) {
println!("Call (Fn) for Foo");
}
}
impl FnMut<()> for Foo {
extern "rust-call" fn call_mut(&mut self, _args: ()) {
println!("Call (FnMut) for Foo");
}
}
impl FnOnce<()> for Foo {
type Output = ();
extern "rust-call" fn call_once(self, _args: ()) {
println!("Call (FnOnce) for Foo");
}
}
fn main() {
let x = Foo;
x();
}
通常情况下,只有一个特质的实现会在其中包含有趣的代码,而其他特征实现会委托给它:
extern "rust-call" fn call(&self, args: ()) {
println!("Foo called, took args: {:?}", args);
}
// ...
extern "rust-call" fn call_mut(&mut self, args: ()) {
self.call(args)
}
// ...
extern "rust-call" fn call_once(self, args: ()) {
self.call(args)
}
另见:
答案 1 :(得分:2)
通过实现 Deref,您可以模拟所需的行为。然后你只需在参数周围使用括号并获得返回值,就像调用函数一样。
请参阅此主题:https://users.rust-lang.org/t/callable-struct-on-stable/54689/6
相关部分(感谢crawdad):
fn main() {
let func: Functionish = make_func();
func();
}
fn make_func() -> Functionish {
Functionish {
f: Box::new(|| println!("printing")),
}
}
struct Functionish {
f: Box<dyn Fn()>,
}
impl std::ops::Deref for Functionish {
type Target = dyn Fn();
fn deref(&self) -> &Self::Target {
&self.f
}
}
这是我自己代码中的一个不完整示例,它采用参数,一个是引用,一个是可变引用。就我而言,闭包存储在 Rc 中,这需要奇数行 &(*self.function_container)
,因为我需要先进入 Rc,然后才能获得对闭包的引用。
pub struct FeelFunction {
pub function_type: FunctionType,
name_container: RefCell<String>,
function_container: Rc<dyn Fn(&FeelValue, &mut NestedContext) -> FeelValue>
}
impl Deref for FeelFunction {
type Target = dyn Fn(&FeelValue, &mut NestedContext) -> FeelValue;
fn deref(&self) -> &Self::Target {
&(*self.function_container)
}
}