问题
#![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();
}
I implemented the Add
trait, but I don't understand how to call the struct as a function. I get the error:
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
I'm new to Rust, and can't find examples how to make this thing happen.
回答1:
You cannot yet implement the Fn*
traits in stable Rust. This is only possible with the nightly compiler using #[feature]
!
It's very useful to fully read the trait that you are implementing to see how to implement it. The Fn trait is defined as:
pub trait Fn<Args>: FnMut<Args> {
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
Notice any differences between the implementation and the definition? I see many:
The implementation doesn't provide a value for
Args
! That's what the compiler is pointing at. See also Wrong number of type arguments: expected 1 but found 0The implementation doesn't implement the supertrait FnMut, which itself requires the supertrait FnOnce.
FnOnce
is where the associated typeOutput
is declared.The implementation neglects to define what concrete type
Output
should be.The implementation returns
Self
while the trait returnsSelf::Output
.The implementation doesn't accept the second argument to
call
. This argument contains any arguments passed in.
Additionally, types in Rust use PascalCase
, not snake_case
, so it should be 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();
}
Normally though, only one trait's implementation would have interesting code in it and the other trait implementations would delegate to it:
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)
}
See also:
- What is a crate attribute and where do I add it?
来源:https://stackoverflow.com/questions/42859330/how-do-i-make-a-struct-callable