Generics

Generics (or templates) allow methods and classes to manipulate generic data types.

C++

Rust

Java


template<typename T>
class generic_class {
  T t;
public:
  generic_class(const T &t)
    : t(t) { }
};

template<typename T>
T do_nothing(const T &t) {
  return t;
}

int main(int argc, char **argv) {
  generic_class<int> gc_int(2);
  generic_class<float> gc_float(2.3);

  int r1 = do_nothing(2);
  float r2 = do_nothing(2.3);

  return 0;
}


#[allow(dead_code)]
struct GenericStruct<T> {
  t: T
}

fn do_nothing<T>(t: T) -> T {
  return t;
}

#[allow(unused_variables)]
fn main() {
  let gc_int = GenericStruct{t: 2};
  let gc_float = GenericStruct{t: 2.3};

  let r1 = do_nothing(2);
  let r2 = do_nothing(2.3);
}


public static class GenericClass<T> {
  private T t;
  
  public GenericClass(T t) {
    this.t = t;
  }
}

public static <T> T do_nothing(T t) {
  return t;
}

public static void main(String[] args) {
  GenericClass<Integer> gc_int
    = new GenericClass<>(2);
  GenericClass<Float> gc_float
    = new GenericClass<>(2.3f);

  int r1 = do_nothing(2);
  float r2 = do_nothing(2.3f);
}



Rust's type system allows it to determine the types used in GenericStruct and do_nothing without needing to specify the exact type. Whereas in both C++ and Java types must be specified for the classes.