I am writing a radix sort function in Rust that can handle vectors containing i32, i64, u8, u16, or so on. I did not find any trait that can represent integers, so initially I tried T: Into<isize> From<isize>
, but From<isize>
is not implemented for u8 or for a bunch of other types. I wonder if there is one trait that is implemented by all the primitive integer types and can be used here? Or what should the bound be if there is none?
P.S. I also tried T: Div<isize> Rem<isize>
, but the compiler said that the <T as Div>::Output
and <T as Rem>::Output
cannot be used as array index.
CodePudding user response:
I wonder if there is one trait that is implemented by all the primitive integer types and can be used here?
The num
crate provides such a trait, but I'm not sure it would be terribly useful to you here. It sounds like at the end of your operation, you need a usize
to be able to index an array, so you want to accept "some integer type," do some math with it, then get a usize
out the other end.
You might be interested in the TryInto
trait, which is like Into
but specifies a possibly-fallible conversion. If you make your own function fallible, this would be an appropriate way to accept multiple integer types.
The Div
and Rem
bounds need to specify the output type, because right now the output is unbounded meaning you could get any type from their invocations; it wouldn't even have to be a numeric type.
However, assuming you need to keep isize
as the intermediate type, you could just do something like this and forgo the Div
and Rem
bounds entirely:
enum FooError {
IntConversion,
OutOfSliceBounds,
}
fn foo<T: TryInto<isize>, V>(n: T, slice: &[V]) -> Result<&V, FooError>
{
let n: isize = n.try_into().map_err(|_| FooError::IntConversion)?;
// Do some math on n, then...
let n: usize = n.try_into().map_err(|_| FooError::IntConversion)?;
slice.get(n).ok_or(FooError::OutOfSliceBounds)
}
If isize
is not large enough to be the intermediate type you could use a larger integer type, but to index a slice you have to be able to convert the final result to usize
.
If the domain of usize
is suitable for the math operations, you could just accept T: TryInto<usize>
and then you don't need the second conversion at all.