I was trying to write a generic function that could take a &str
containing either a decimal representation 123
, or a hexadecimal representation 0xFF
and parse this into a decimal number.
use num_traits::Num;
fn parse<T>(value: &str) -> T
where T: Num + FromStr, <T as std::str::FromStr>::Err: std::fmt::Debug {
let value = value.trim();
if value.starts_with("0x") {
<T>::from_str_radix(value.strip_prefix("0x").unwrap(), 16).ok().unwrap()
} else {
value.parse::<T>().unwrap()
}
}
I didn't really have any idea what i was doing, i do understand the basics of traits and generics, but this was way out of my league. So i have some questions about this:
what does FromStr, <T as std::str::FromStr>::Err: std::fmt::Debug
actually mean? i have only seen syntax like <T: Foo + Bar>
but i don't really understand why all that is needed? and i have never seen this type of syntax in generic functions before.
Also when i remove the return type of T
and try to return a Result<T, Box<dyn Error>>
and then remove all the unwrap
and ok
and instead use the ?
fn parse<T>(value: &str) -> Result<T, Box<dyn Error>>
where T: Num + FromStr, <T as std::str::FromStr>::Err: std::fmt::Debug {
let value = value.trim();
if value.starts_with("0x") {
<T>::from_str_radix(value.strip_prefix("0x").unwrap(), 16)?
} else {
value.parse::<T>()?
}
}
i get this error from the compiler
try expression alternatives have incompatible types
expected enum `std::result::Result<T, Box<(dyn std::error::Error + 'static)>>`
found type parameter `T`rustcE0308
options.rs(51, 14): this type parameter
options.rs(55, 13): try using a variant of the expected enum
Which i as a beginner have a really hard time understanding, it looks like it still wants to return the T
type?