Make function polymorphic


#1

Let us assume I have this:

fn to_number(s: &str) -> u32 {
    s.parse::<u32>().unwrap_or_else(|e| {
        eprintln!("Not a number: {}", e);
        ::std::process::exit(1);
    })
}

and I want it for other numbers as well (i32,…).

When I try:

fn to_number<T>(s: &str) -> T {
    s.parse::<T>().unwrap_or_else(|e| {
        eprintln!("Not a number: {}", e);
        ::std::process::exit(1);
    })
}

I get

–> src/main.rs:94:7
|
94 | s.parse::().unwrap_or_else(|e| {
| ^^^^^ the trait std::str::FromStr is not implemented for T
|
= help: consider adding a where T: std::str::FromStr bound

error: aborting due to previous error

So I need some kind of contraint. Not sure how exactly to make the compiler happy.


#2
use std::str::FromStr

fn to_number<T>(s: &str) -> T
// this is exactly the compiler suggestion at line 6
// (= help: consider adding a where T: std::str::FromStr bound)
    where T: std::str::FromStr {
    s.parse::<T>().unwrap_or_else(|e| {
        eprintln!("Not a number: {}", e);
        ::std::process::exit(1);
    })
}

#3

Thanks.

Overlooked. Perhaps because I’vn never seen the where clause before.

I had to add some more stuff. The following is working fine:

fn to_number<T>(s: &str) -> T
// this is exactly the compiler suggestion at line 6
// (= help: consider adding a where T: std::str::FromStr bound)
where  T:std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Display
 {
    s.parse::<T>().unwrap_or_else(|e| {
        eprintln!("String {} is not a number because {}", s, e);
        ::std::process::exit(1);
    })
}

#4

Note you can shorten <T as std::str::FromStr>::Err to just T::Err there.


#5

Oh, yes. Thanks for this.