# Maths operations on a tuple struct

**URL:** <https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779>\
**Category:** help\
**Created:** [October 7, 2020, 11:16am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779 "2020-10-07T11:16:33Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![arifd](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/arifd/32/17291_2.png) [@arifd](https://users.rust-lang.org/u/arifd)\
**Post date:** [October 7, 2020, 11:16am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/1 "2020-10-07T11:16:33Z")

</div>

Hi, I'm trying to use the newtype pattern to avoid bugs and be a better programmer 🙂

I have `struct Foo(usize)`

I want to be able to %, /, \>=, +, - all with other usizes.

`Add` and `Sub`, `Div` and `Rem` have been easy: (example)

```rust
impl std::ops::Add<usize> for Foo {
    type Output = Self;

    fn add(self, other: usize) -> Self::Output {
        Self(self.0 + other)
    }
}

```

But I'm really struggling with the compare operators. they require a number of previous Traits to also be implemented, and I'm getting lost in the woods a little.

Please help!

---

<div class="post-metadata">

**Author:** ![nologik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/nologik/32/23342_2.png) [@nologik](https://users.rust-lang.org/u/nologik)\
**Post date:** [October 7, 2020, 11:27am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/2 "2020-10-07T11:27:28Z")

</div>

> **[PartialOrd in std::cmp - Rust](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html)**
>
> Trait for types that form a partial order.

Could you show us your `Foo` structure?

---

<div class="post-metadata">

**Author:** ![arifd](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/arifd/32/17291_2.png) [@arifd](https://users.rust-lang.org/u/arifd)\
**Post date:** [October 7, 2020, 11:28am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/3 "2020-10-07T11:28:16Z")

</div>

it is a tuple struct, litterally that: `struct Foo(usize)`

---

<div class="post-metadata">

**Author:** ![nologik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/nologik/32/23342_2.png) [@nologik](https://users.rust-lang.org/u/nologik)\
**Post date:** [October 7, 2020, 11:35am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/4 "2020-10-07T11:35:07Z")

</div>

```rust
#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
struct Foo(usize);

impl std::ops::Add<Foo> for Foo {
    type Output = Self;

    fn add(self, other: Foo) -> Self::Output {
        Self(self.0 + other.0)
    }
}

impl std::ops::Add<usize> for Foo {
    type Output = Self;

    fn add(self, other: usize) -> Self::Output {
        Self(self.0 + other)
    }
}

impl std::fmt::Display for Foo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

fn main() {
    let foo1 = Foo(0);
    let foo2 = Foo(15);
    let foo3 = Foo(20);
    let foo4 = Foo(0);
    
    println!("{}, {}, {}", foo1 == foo2, foo2 == foo3, foo1 == foo4);
    println!("{}", foo1 + foo2 + foo3);
    println!("{}", foo1 < foo2);
    println!("{}", foo1 + 10usize);
}

```

---

<div class="post-metadata">

**Author:** ![arifd](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/arifd/32/17291_2.png) [@arifd](https://users.rust-lang.org/u/arifd)\
**Post date:** [October 7, 2020, 11:37am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/5 "2020-10-07T11:37:54Z")

</div>

Thank you very much, but I want to compare it with a `usize`, not with another of itself... i.e. `if foo > 14 {...}`

So you can't use #[derive] in this case as all the ops need to be `<usize> for Foo`

---

<div class="post-metadata">

**Author:** ![nologik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/nologik/32/23342_2.png) [@nologik](https://users.rust-lang.org/u/nologik)\
**Post date:** [October 7, 2020, 11:42am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/6 "2020-10-07T11:42:53Z")

</div>

We can only compare equal types. However, thanks to rust's zero-cost abstractions, you can implement this:

```rust
impl From<usize> for Foo {
    fn from(value: usize) -> Self {
        Self(value)
    }
}

```

Then, call `.into()` on the `usize` value:

```rust
    println!("{}", foo2 < (10usize).into())

```

---

<div class="post-metadata">

**Author:** ![arifd](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/arifd/32/17291_2.png) [@arifd](https://users.rust-lang.org/u/arifd)\
**Post date:** [October 7, 2020, 11:45am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/7 "2020-10-07T11:45:28Z")

</div>

Ah really!? But Foo _is_ a usize! 😥

What about something like `impl Deref` for Foo?

---

<div class="post-metadata">

**Author:** ![nologik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/nologik/32/23342_2.png) [@nologik](https://users.rust-lang.org/u/nologik)\
**Post date:** [October 7, 2020, 11:47am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/8 "2020-10-07T11:47:30Z")

</div>

```rust
impl std::ops::Deref for Foo {
    type Target = usize;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

```

Then, do this:

```rust
println!("{}", *foo2 < 10usize)

```

Good idea. Looks much cleaner

---

<div class="post-metadata">

**Author:** ![arifd](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/arifd/32/17291_2.png) [@arifd](https://users.rust-lang.org/u/arifd)\
**Post date:** [October 7, 2020, 11:49am UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/9 "2020-10-07T11:49:43Z")

</div>

Ah nice, so then, I don't need to impl any maths operations at all now, right. It's now just a straight up usize

---

<div class="post-metadata">

**Author:** ![Cerber-Ursi](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/cerber-ursi/32/8315_2.png) [@Cerber-Ursi](https://users.rust-lang.org/u/Cerber-Ursi)\
**Post date:** [October 7, 2020, 1:14pm UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/11 "2020-10-07T13:14:37Z")

</div>

> [@nologik](#):
>
> We can only compare equal types.

Well, [not only](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=080a0b0806b97549e50bda38906864eb):

```rust
use core::cmp::Ordering;
use std::cmp::{PartialOrd, PartialEq};

struct Foo(usize);

impl PartialEq<usize> for Foo {
    fn eq(&self, other: &usize) -> bool {
        self.0.eq(other)
    }
}

impl PartialOrd<usize> for Foo {
    fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
        self.0.partial_cmp(other)
    }
}

fn main() {
    assert!(Foo(1) > 0);
}

```

---

<div class="post-metadata">

**Author:** ![arifd](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/arifd/32/17291_2.png) [@arifd](https://users.rust-lang.org/u/arifd)\
**Post date:** [October 7, 2020, 1:15pm UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/12 "2020-10-07T13:15:26Z")

</div>

Wow, snap!

I just concurrently figured it out myself!

```rust
use std::cmp::{PartialOrd, Ordering};

struct Foo(usize);

impl PartialEq<usize> for Foo {
    fn eq(&self, other: &usize) -> bool {
        self.0 == *other
    }
}

impl PartialOrd<usize> for Foo {
    fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
        Some(self.0.cmp(&other))
    } 
}

fn main() {
    dbg!(Foo(0) < 1usize);
}

```

Freaky

---

<div class="post-metadata">

**Author:** ![nologik](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/nologik/32/23342_2.png) [@nologik](https://users.rust-lang.org/u/nologik)\
**Post date:** [October 7, 2020, 3:10pm UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/13 "2020-10-07T15:10:49Z")

</div>

I didn't see that in the docs for PartialOrd in the code section ([PartialOrd in std::cmp - Rust](https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html)). They should make it more explicit in the examples. Good to know something new!

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [January 5, 2021, 3:10pm UTC](https://users.rust-lang.org/t/maths-operations-on-a-tuple-struct/49779/14 "2021-01-05T15:10:54Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
