Generic trait for simple and complex T

I want a generic trait that takes a slice of T and then does something with T, but what if T is complex? Is there a way to have an implementation for [T] where T is simple type like i32 and additional implementation for [T] where T is a struct with a field, a collection, or tuple where that implementation will address a certain field of T? For example something like

  trait MyTrait<T> {
     fn my_trait_method(&self, arg: &T) -> Vec<T>;
  }
  impl<T: Clone + Eq> MyTrait<T> for [T] {
     fn  my_trait_method(&self, arg:&T) -> Vec<T> {
        self.to_owned()
            .into_iter()
            .filter(|val| val == arg)
            .collect()
      }
   }

How should I write second impl for [T] which will take additional parameter in my_trait_method, representing a field I want to refer? Suppose my_trait_method takes 3 parameters, but for simple T 3rd parameter will be T, and for complex T 3rd parameter will be some field on T.

Rust doesn't differentiate between "simple" and "complex" types. You can write functions with absolutely any parameter type you like, and you can be generic over primitive as well as user-defined types. What are you actually trying to do?

There's no way to specify fields of generics. The closest you can get is a trait that has some getter-like methods.

Maybe you want something like

trait MyTrait<T> {
    fn my_trait_method<P>(&self, predicate: P) -> Vec<T>
    where
        P: FnMut(&T) -> bool;
}

impl<T: Clone + Eq> MyTrait<T> for [T] {
    fn my_trait_method<P: FnMut(&T) -> bool>(&self, mut predicate: P) -> Vec<T> {
        self.iter()
            .filter(|&t| predicate(t)) // go from &&T to &T
            .cloned()                  // clone after filtering
            .collect()
    }
}

That would allow implementers of the trait to specify some more complicated way of filtering (if that is what you are trying to do).

Looks like it! Thanks, I'll try that

I'm trying to write a function that will take a slice of T a var of type T and filter (in this example) by a certain field. Suppose I have a collection of tuples of 2 values and a collection of structs with 3 fields, and if I want to be able to write both
tuple_collection.my_method(a_tuple, a_tuple.1) and struct_collection.my_method(a_struct, a_struct.name) and maybe also f64_collection.my_method(a_f64, Self). But maybe I'm going in a wrong direction.

Indeed, if you want to support arbitrary projections, then the easiest way is to take a closure and performs the projection, regardless to what kind of type you have.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.