Generic over all integer types


#1

If I want LoopInt (below) to work for i32, I have to copy & paste the whole impl. Is there any other way to do this?

trait LoopInt {
    fn increment(&mut self, max: Self);
    fn decrement(&mut self, max: Self);
}

impl LoopInt for usize {
    fn increment(&mut self, max: Self) {
        if *self == max-1 { *self = 0 } else { *self += 1 }
    }
    fn decrement(&mut self, max: Self) {
        if *self == 0 { *self = max-1 } else { *self -= 1 }
    }
}

#2

You could require it implement the traits Add, AddAssign and Sub. If I remember right assign zero in a generic brings in some weird issues, but I can’t remember what they are.


#3

Okay, I looked up what the weird issue I was remembering with zero. The generic zero in std lib has been deprecated and the replacement I found was: http://rust-num.github.io/num/num/trait.Zero.html


#4

Yeah, you can require generic ops, but you’ll probably need num's Zero and One to complete this. There’s a PrimInt trait which encapsulates a lot of the generic traits.

extern crate num_traits;

use num_traits::PrimInt;

trait LoopInt {
    fn increment(&mut self, max: Self);
    fn decrement(&mut self, max: Self);
}

impl<I> LoopInt for I
    where I: PrimInt
{
    fn increment(&mut self, max: Self) {
        if *self == max - Self::one() {
            *self = Self::zero()
        } else {
            *self = *self + Self::one()
        }
    }
    
    fn decrement(&mut self, max: Self) {
        if *self == Self::zero() {
            *self = max - Self::one()
        } else {
            *self = *self - Self::one()
        }
    }
}

playground


#5

Thanks for the quick responses~!

sadly I can’t use extern crate for project on hand, thanks anyway~~ :relaxed:


#6

Well, it wouldn’t be too horrible to approximate that by hand, something like

trait MyInteger: Copy + Add<Output=Self> /* etc. */ {
    fn zero() -> Self;
    fn one() -> Self;
}

/* repeat this for all integers, perhaps using a macro */
impl MyInteger for usize {
    fn zero() -> Self { 0 }
    fn one() -> Self { 1 }
}

#7

aha~! coming from Java/C#, I forgot about macro completely~
thank you~~ :sunglasses:


#8

I’m curious. Why no external crates? Is it a weird target?


#9

One of the weirdest target of all: CodinGame


#10

Interesting, didn’t knew they had rust support already.