我将为坐标创建一个泛型类型.它应该能够 for each 轴指定基数类型.

起初,我的代码如下所示:

use num::Signed;

struct Coordinate<Index: Signed> {
  x: Index,
  y: Index,
}

此外,我希望它携带额外的绑定信息,以帮助我判断实现中的访问权限,所以我写了以下内容.

use num::Signed;

struct Coordinate<const Bound: isize, Index: Signed> {
  x: Index,
  y: Index,
}

然而,即使只对i8, ..., isize执行Signed,我也不能简单地将Signed的值与isize进行比较.所以我求助于这个:

use num::Signed;

struct Coordinate<const Bound: Index, Index: Signed> {
  x: Index,
  y: Index,
}

当然,它失败了.我想知道有没有可能解决这个问题的办法.

推荐答案

你的第一个版本是在正确的方向上,它只需要一些更多的特征界限:

use num::Signed;

#[derive(Debug)]
struct Coordinate<const BOUND: isize, Index>
where
    Index: Signed + PartialOrd + Copy,
    isize: From<Index>,
{
    x: Index,
    y: Index,
}

impl<const BOUND: isize, Index> Coordinate<BOUND, Index>
where
    Index: Signed + PartialOrd + Copy,
    isize: From<Index>,
{
    pub fn new(x: Index, y: Index) -> Option<Self> {
        if x >= Index::zero()
            && y >= Index::zero()
            && isize::from(x) < BOUND
            && isize::from(y) < BOUND
        {
            Some(Self { x, y })
        } else {
            None
        }
    }
}

fn main() {
    dbg!(Coordinate::<10, i16>::new(5, 3));
    dbg!(Coordinate::<10, i16>::new(5, 11));
}
[src\main.rs:32] Coordinate::<10, i16>::new(5, 3) = Some(
    Coordinate {
        x: 5,
        y: 3,
    },
)
[src\main.rs:33] Coordinate::<10, i16>::new(5, 11) = None

虽然PartialOrd + Copy看起来很乏味,而且都已经被PrimInt覆盖了,但我还是会用那个来代替.

此外,您的问题中没有任何内容需要Signed,所以我会删除它,直到实际需要为止.

use num::PrimInt;

#[derive(Debug)]
struct Coordinate<const BOUND: isize, Index>
where
    Index: PrimInt,
    isize: From<Index>,
{
    x: Index,
    y: Index,
}

impl<const BOUND: isize, Index> Coordinate<BOUND, Index>
where
    Index: PrimInt,
    isize: From<Index>,
{
    pub fn new(x: Index, y: Index) -> Option<Self> {
        if x >= Index::zero()
            && y >= Index::zero()
            && isize::from(x) < BOUND
            && isize::from(y) < BOUND
        {
            Some(Self { x, y })
        } else {
            None
        }
    }
}

fn main() {
    dbg!(Coordinate::<10, i16>::new(5, 3));
    dbg!(Coordinate::<10, i16>::new(5, 11));
}
[src\main.rs:32] Coordinate::<10, i16>::new(5, 3) = Some(
    Coordinate {
        x: 5,
        y: 3,
    },
)
[src\main.rs:33] Coordinate::<10, i16>::new(5, 11) = None

Rust相关问答推荐

什么是谓词的简短和简洁类型

如何仅使用http机箱发送http请求?

为什么我不能从带有字符串的 struct 的引用迭代器中收集VEC<;&;str&>?

为什么TcpListener的文件描述符和生成的TcpStream不同?

如何从ruust中的fig.toml中读取?

如何在函数中返回自定义字符串引用?

为什么`str`类型可以是任意大小(未知大小),而`string`类型的大小应该是已知的?

为什么&;mut buf[0..buf.len()]会触发一个可变/不可变的borrow 错误?

为什么Option类型try块需要类型注释?

如何获取光标下的像素 colored颜色 ?

确保参数是编译时定义的字符串文字

Rust,如何从 Rc> 复制内部值并返回它?

Rust Option 的空显式泛型参数

在每个循环迭代中删除borrow

RAII 模式的 Rust 解决方案,用于在 new() 和 drop() 上修改另一个对象

Rust HRTB 是相同的,但编译器说一种类型比另一种更通用

tokio async rust 的 yield 是什么意思?

类型组的通用枚举

如果返回类型是通用的,我可以返回 &str 输入的一部分吗?

类型参数不受 impl 特征、自身类型或谓词的约束