Reputation: 23
I can't think of a way to get the functionality below, without the use of unconstrained types.
struct Things<T> {
thing: T
}
trait ThingActions<D> {//will be implemented for 'D's of different types
fn foo(&self, data: D) {}
fn bar(&self, data: D) {}
}
impl<T: ThingActions<D>, D> Things<T> {
fn do_foos(&self, data: D) {//any D with corresponding foo can be used here
self.thing.foo(data)
}
}
impl<T: ThingActions<D>, D: Send + Sync> Things<T> {
fn do_bars_multithreaded(&self, data: D) {
self.thing.bar(&self.thing, data)//this happens in a different thread
}
}
My end goal is to have the code below work for any configuration of foo and bar, with relatively few changes to it.
fn main(){
let number = Things {thing: 5isize};
number.do_foos(2);
number.do_foos('a');
}
impl ThingActions<isize> for isize {
fn foo(&self, data: isize){
println!("{}", data + self)
}
}
impl ThingActions<char> for isize {
fn foo(&self, data: char){
println!("{}, {}", data, self)
}
}
There are also possible situations where none of this is used except "Things".
Upvotes: 0
Views: 27
Reputation: 35973
You could try to bound D
only on the fn
, and not on the whole struct:
struct Things<T> {
thing: T
}
trait ThingActions<D> {//will be implemented for 'D's of different types
fn foo(&self, data: D) {}
fn bar(&self, data: D) {}
}
impl<T> Things<T> {
fn do_foos<D>(&self, data: D)
where T: ThingActions<D>
{//any D with corresponding foo can be used here
self.thing.foo(data)
}
}
impl<T> Things<T> {
fn do_bars_multithreaded<D>(&self, data: D)
where T: ThingActions<D>, D: Send + Sync
{
self.thing.bar(data)//this happens in a different thread
}
}
fn main(){
let number = Things {thing: 5isize};
number.do_foos(2);
number.do_foos('a');
}
impl ThingActions<isize> for isize {
fn foo(&self, data: isize){
println!("{}", data + self)
}
}
impl ThingActions<char> for isize {
fn foo(&self, data: char){
println!("{}, {}", data, self)
}
}
Upvotes: 1