Now that we know a bit about traits and generics, let's dive into trait bounds. Trait bounds allow you to specify that a generic type must implement a particular trait. This ensures that only types with certain capabilities can be used with your generic code.
For example:
- A generic function can be constrained to types that implement the
std::fmt::Displaytrait for printing. - A generic struct can be limited to types that implement traits like
PartialOrdfor comparison.
Trait bounds make your code flexible while maintaining strong type safety.
Syntax
You can specify trait bounds in two ways:
-
Inline: Specify the trait bounds after the
implorfnkeyword.fn my_function<T: Trait1 + Trait2>(value: T) {// code here} -
Where clause: Use a
whereclause to specify trait bounds.fn my_function<T>(value: T)whereT: Trait1 + Trait2,{// code here}
This means that the generic type T must implement both Trait1 and Trait2.
Your Task
-
Define a generic function
compare_and_displaythat:- Takes two parameters of the same type.
- Prints both parameters using the
Displaytrait. - Returns the greater of the two using the
PartialOrdtrait.
-
Use trait bounds to ensure the function works only with types that implement both
DisplayandPartialOrd.
Hints
If you're stuck, here are some hints to help you solve the challenge:
<details> <summary>Click here to reveal hints</summary>- Use
std::cmp::PartialOrdto compare values. - Use
std::fmt::Displayto print values with theprintln!macro. - You can write trait bounds inline with
T: Trait1 + Trait2or using awhereclause. e.g.fn my_function<T: Trait1 + Trait2>(value: T) {// code here}
// TODO: Define the generic function `compare_and_display` with appropriate trait bounds.pub fn compare_and_display // Complete the function definition// Example usagepub fn main() {let greater = compare_and_display(10, 20);println!("Greater value: {}", greater);let greater = compare_and_display("Apple", "Orange");println!("Greater value: {}", greater);}