Szegoo
Szegoo

Reputation: 297

Rust adding associated type with u32

I have an associated type MyType.

This type is going to be an unsigned integer, but I use it because the size of the unsigned integer required for this variable is maybe going to change in the future. So MyType is going to be one of: u32, u64, u128.

So MyType will look like this when defined: MyType = u32 (of course it may not be u32).

In my code, I need to increment this variable of type MyType by one.

so I have to do this: let n: MyType = v + 1, where v is the type of MyType.

How can I do this, what trait restrictions should MyType have?

I would want something like this: type MyType: UnsignedInt, but the problem is there is no number trait in rust as far as I have seen.

Upvotes: 0

Views: 644

Answers (2)

Chayim Friedman
Chayim Friedman

Reputation: 71025

The + operator behavior is specified by the trait std::ops::Add. This trait is generic over its output type, so if you want for example MyType to have the semantics MyType + MyType = MyType you can write:

trait MyTrait {
    type MyType: std::ops::Add<Output = Self::MyType>;
}

All integers will implement this. If you need additional operators you can use the traits from std::ops, but with multiple bounds this can become tedious. The crate num-traits can help you with pre-declared traits that has all required ops and more. For example the trait NumOps specify all arithmetic operators, and there are more traits such as Num that includes equality and zero/one or PrimInt that specifies basically every operation or method integers in Rust have.

Upvotes: 0

Finomnis
Finomnis

Reputation: 22601

Your description is very vague and it would be much easier if you added a code example, but deriving from the word associated type I tried to reconstruct a minimal example:

trait Incrementor {
    type MyType;

    fn increment(&self, value: Self::MyType) -> Self::MyType {
        value + 1
    }
}

struct U32Incrementor;
impl Incrementor for U32Incrementor {
    type MyType = u32;
}

fn main() {
    let incrementor = U32Incrementor;

    println!("{}", incrementor.increment(10));
}
error[E0369]: cannot add `{integer}` to `<Self as Incrementor>::MyType`
 --> src/main.rs:5:15
  |
5 |         value + 1
  |         ----- ^ - {integer}
  |         |
  |         <Self as Incrementor>::MyType
  |
  = note: the trait `std::ops::Add` is not implemented for `<Self as Incrementor>::MyType`

Is that about the problem you are having?

If yes, does this help?

use num_traits::{FromPrimitive, One, Unsigned};

trait Incrementor {
    type MyType: Unsigned + FromPrimitive;

    fn increment(&self, value: Self::MyType) -> Self::MyType {
        value + Self::MyType::one()
    }

    fn increment_ten(&self, value: Self::MyType) -> Self::MyType {
        value + Self::MyType::from_u8(10).unwrap()
    }
}

struct U32Incrementor;
impl Incrementor for U32Incrementor {
    type MyType = u32;
}

fn main() {
    let incrementor = U32Incrementor;

    println!("{}", incrementor.increment(10));
    println!("{}", incrementor.increment_ten(10));
}
11
20

It's based on the excellent num_traits crate.

Upvotes: 2

Related Questions