Generic Type Parameters in Rust

Introduction:


Unlock the power of generics in Rust with this concise code example. Learn how to define and leverage generic types using the Query struct, which takes a flexible type parameter T. The accompanying meh function showcases the versatility of generics by accepting a Query<i32> instance. Discover the elegance and expressiveness of Rust’s generic programming capabilities in this illustrative snippet.

Why use generics?


In Rust, generics provide a robust mechanism for writing flexible and reusable code. The Query struct exemplifies this concept, designed with a type parameter T to accommodate various data types seamlessly. The meh function, tailored to accept a Query<i32> instance, demonstrates how generics empower developers to create functions and structures that work across different data types.

By embracing generics, Rust promotes code that is not only concise but also type-safe. The Query struct and meh function encapsulate the essence of generic programming, allowing for cleaner and more modular code. This example serves as a stepping stone for developers looking to harness the full potential of generics in Rust, fostering code that is both efficient and adaptable.

Define a generic struct Query with a type parameter T:

struct Query<T> {
    data: T,
}

Define a function meh that takes a Query with a generic type parameter:

fn meh(query: Query<i32>) {
    // Some logic using the Query<i32> type
    println!("Query data: {}", query.data);
}

In the main function, create a Query<i32> instance and pass it to the meh function:

fn main() {
    // Create a Query<i32> instance and pass it to the meh function
    let query_instance = Query { data: 42 };
    meh(query_instance);
}

// Define a generic struct Query with a type parameter T
struct Query<T> {
    data: T,
}

// Define a function meh that takes a Query with a generic type parameter
fn meh(query: Query<i32>) {
    // Some logic using the Query<i32> type
    println!("Query data: {}", query.data);
}

fn main() {
    // Create a Query<i32> instance and pass it to the meh function
    let query_instance = Query { data: 42 };
    meh(query_instance);
}

More generic

To make the Query struct generic and accept both i32 and f64, you can use a generic type parameter. Here’s how you can modify your code:

// Generic struct
struct Query<T> {
    data: T,
}

// Function accepting Query with a generic type parameter
fn meh<T>(query: Query<T>)
where
    T: std::fmt::Debug,
{
    println!("{:?}", query.data);
}

fn main() {
    // Create instance of struct with i32
    let res = Query { data: 39 };
    // Use struct instance in function
    meh(res);

    // Create instance of struct with f64
    let res2 = Query { data: 21.2 };
    meh(res2);
}

In this modified code:

  • The Query struct now has a generic type parameter T.
  • The meh function is also generic, accepting a Query<T> where T is the type parameter. The where T: std::fmt::Debug constraint ensures that the type T must implement the Debug trait, allowing it to be printed with println!("{:?}", query.data).
  • In the main function, you can create instances of Query with both i32 and f64, and pass them to the meh function.

This way, the Query struct becomes more flexible and can be used with various types, including i32 and f64.

Previous article

This should not compile?

Next article

Dereference