有没有办法创建只接受一系列值的数据类型? [英] Is there a way to create a data type that only accepts a range of values?

查看:30
本文介绍了有没有办法创建只接受一系列值的数据类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数接受 u16 类型的参数.是否有一种优雅的方式来定义行为与 u16 完全相同但只有 0 到 100 之间的值的自定义数据类型?

I have a function that takes an argument of type u16. Is there an elegant way to define a custom data type that behaves exactly like a u16 but only has values between 0 and 100?

推荐答案

据我所知,这需要 依赖类型,Rust 没有. 这不需要依赖类型(见评论)但 Rust 仍然没有所需的支持.

As I understand it, that requires dependent types, which Rust does not have. This doesn't require dependent types (see comments) but Rust still doesn't have the support needed.

作为一种解决方法,您可以创建一个您自己验证的新类型:

As a workaround, you could create a newtype that you verify yourself:

#[derive(Debug)]
struct Age(u16);

impl Age {
    fn new(age: u16) -> Option<Age> {
        if age <= 100 {
            Some(Age(age))
        } else {
            None
        }
    }
}

fn main() {
    let age1 = Age::new(30);
    let age2 = Age::new(500);

    println!("{:?}, {:?}", age1, age2);
    assert_eq!(
        std::mem::size_of::<Age>(),
        std::mem::size_of::<u16>()
    );
}

当然,它的行为完全不像u16,但您也不希望它如此!例如,一个 u16 可以超过 100...你必须考虑添加/减去/乘/除等你的新类型是否有意义.

Of course, it doesn't behave exactly like a u16, but you don't want it to, either! For example, a u16 can go beyond 100... You'd have to reason out if it makes sense to add/subtract/multiply/divide etc your new type as well.

为了最大限度地保护,您应该将您的类型和任何相关功能移动到一个模块中.这利用了 Rust 的可见性规则来防止人们意外访问 newtype 中的值并使约束失效.

For maximum safeguarding, you should move your type and any associated functions into a module. This leverages Rust's visibility rules to prevent people from accidentally accessing the value inside the newtype and invalidating the constraints.

您可能还想实现 TryFrom(从 u16 到您的类型)或 From(从您的类型到 u16)以更好地与通用代码集成.

You may also want to implement TryFrom (from u16 to your type) or From (from your type to u16) to better integrate with generic code.

需要注意的重要一点是,这个 newtype 占用的空间与 u16 相同——在编译代码时,包装器类型被有效地擦除.类型检查器确保在那之前所有的东西都啮合.

An important thing to note is that this newtype takes the same amount of space as a u16 - the wrapper type is effectively erased when the code is compiled. The type checker makes sure everything meshes before that point.

这篇关于有没有办法创建只接受一系列值的数据类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆