I'm trying to make my own implementation of big integers (just for education). The implementation is generic by data type:
struct LongNum<T>
where T: Integer + MulAssign + CheckedMul + CheckedAdd + Copy + From<u8>
{
values: Vec<T>,
powers: Vec<u8>,
radix: u8,
}
The problem is that I need to repeat this verbose constraint for T in all impls. It's too cumbersome.
I can make my own trait combining these constraints, like this:
trait LongNumValue: Integer + MulAssign + CheckedMul + CheckedAdd + Copy + From<u8> {}
struct LongNum<T: LongNumValue>
{
values: Vec<T>,
powers: Vec<u8>,
radix: u8,
}
But in this case I have to add impls for this LongNumValue trait to all types which can be used in LongNum:
impl LongNumValue for u8 {}
impl LongNumValue for u16 {}
impl LongNumValue for u32 {}
...
This means that if I don't add some type to this list of impls, the user of my crate will be unable to use this type for LongNum, even if this type is passes all constraints.
Is there any way to avoid writing long repetitive costraints without adding unnecessary restrictions to user?
Trait and lifetime bounds provide a way for generic items to restrict which types and lifetimes are used as their parameters. Bounds can be provided on any type in a where clause.
In Rust, generics refer to the parameterization of data types and traits. Generics allows to write more concise and clean code by reducing code duplication and providing type-safety. The concept of Generics can be applied to methods, functions, structures, enumerations, collections and traits.
You can add a blanket implementation:
impl<T> LongNumValue for T
where
T: Integer + MulAssign + CheckedMul + CheckedAdd + Copy + From<u8> {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With