I have the following code
struct MyStruct { val: i32 }
impl MyStruct {
fn foo(&self) { println!("foo"); }
fn bar<F>(&self, f: F) -> i32
where F: Fn(&i32) -> i32, {
f(&self.val)
}
fn baz<F>(&self, f: F) -> i32
where F: Fn(&i32) -> i32, {
f(2 * &self.val )
}
}
This works perfectly, and achieves the following desired behavior:
fn main() {
let item = MyStruct { val: 3 };
item.foo(); // "foo"
print!("{}", item.bar(|x| x + 1)); // 4
print!("{}", item.baz(|x| x + 1)); // 7
print!("{}", item.baz(|x| (x, x))); // mismatched types
}
As you can see, some of the implemented methods share a common bound that must be repeated each time. I’d like to eliminate that repetition, ideally with syntax rather than a macro.
Ideally I would want to replace the impl MyStruct {}
block with the following:
impl MyStruct {
fn foo(&self) { println!("foo"); }
}
impl<F> MyStruct
where F: Fn(&i32) -> i32, {
fn bar(&self, f: F) -> i32 { f(&self.val) }
fn baz(&self, f: F) -> i32 { f(2 * &self.val) }
}
This doesn’t work though, saying that The type parameter "F" is not constrained by the impl trait, self type, or predicates
. I don’t really understand why it would need to be constrained in this case. I also don’t want to solve this with a trait like: MyTrait<F: Fn(&i32) -> i32>
because the overhead of writing accessor functions is no better. My actual use case has a criteria set of more than the one bound, and more than two functions that should be implemented conditionally on whether that criteria set is met.