Types 有没有办法创建一个只接受一系列值的数据类型?

Types 有没有办法创建一个只接受一系列值的数据类型?,types,rust,Types,Rust,我有一个函数,它接受类型为u16的参数。是否有一种优雅的方式来定义一个自定义数据类型,该类型的行为与u16完全相同,但其值仅在0和100之间?据我所知,这需要Rust所没有的。这不需要依赖类型(参见注释),但Rust仍然没有所需的支持 作为一种解决方法,您可以创建一个自己验证的新类型: #[派生(调试)] 结构年龄(u16); 植入年龄{ fn新建(年龄:u16)->选项(从u16到您的类型)或(从您的类型到u16)以更好地与通用代码集成 需要注意的一点是,这种新类型占用的空间与u16相同-在编

我有一个函数,它接受类型为
u16
的参数。是否有一种优雅的方式来定义一个自定义数据类型,该类型的行为与u16完全相同,但其值仅在0和100之间?

据我所知,这需要Rust所没有的。这不需要依赖类型(参见注释),但Rust仍然没有所需的支持

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

#[派生(调试)]
结构年龄(u16);
植入年龄{
fn新建(年龄:u16)->选项(从
u16
到您的类型)或(从您的类型到
u16
)以更好地与通用代码集成


需要注意的一点是,这种新类型占用的空间与
u16
相同-在编译代码时,包装类型会被有效地删除。类型检查器会确保所有内容都在该点之前啮合。

不幸的是,std板条箱内没有这样的内容

但是,您可以通过夜间通用常量以优化的方式自行完成,该常量计划在Rust 1.51中稳定。例如:

//1.51.0-每晚(2020-12-30)
发布结构BoundedI32(i32);
impl BoundedI32{
发布常数低:i32=低;
发布常数高:i32=高;
新发布(n:i32)->Self{
边界32(最小值(自:高)。最大值(自:低))
}

据我所知,pub fn fallible_new(n:i32)->Result不完全正确。但您可以使用特征来接近。例如,其中,吨位是一个无符号8位整数,预计为20-100,是5的倍数:

pub trait Validator{
    fn isvalid(&self) -> bool;
}

pub struct TotalRobotTonnage{
    pub tonnage: u8,
}

impl Validator for TotalRobotTonnage{
    //is in range 20-100 and a multiple of 5
    fn isvalid(&self) -> bool{
        if self.tonnage < 20 || self.tonnage > 100 ||  self.tonnage % 5 != 0{
            false
        }else{
            true
        }
    } 
}

fn main() {
    let validtonnage = TotalRobotTonnage{tonnage: 100};
    let invalidtonnage_outofrange = TotalRobotTonnage{tonnage: 10};
    let invalidtonnage_notmultipleof5 = TotalRobotTonnage{tonnage: 21};
    println!("value {} [{}] value {} [{}] value {} [{}]", 
    validtonnage.tonnage, 
    validtonnage.isvalid(),
    invalidtonnage_outofrange.tonnage, 
    invalidtonnage_outofrange.isvalid(),
    invalidtonnage_notmultipleof5.tonnage, 
    invalidtonnage_notmultipleof5.isvalid()
);
}
pub特征验证程序{
fn有效(&self)->bool;
}
发布结构TotalRobotTonnage{
总吨位:u8,
}
TotalRobotTonnage的impl验证程序{
//在20-100范围内,是5的倍数
fn有效(&self)->bool{
如果自吨位<20 | |自吨位>100 | |自吨位%5!=0{
假的
}否则{
真的
}
} 
}
fn main(){
设validtonnage=TotalRobotTonnage{吨位:100};
让无效吨位超出范围=总机器吨位{吨位:10};
让InvalidTonts_notmultipleof5=总Robottonnage{吨位:21};
println!(“值{}[{}]值{}[{}]值{}[{}]”,
有效吨位,
validtonnage.isvalid(),
无效吨位/超出范围的吨位,
InvalidTonts\u超出范围。isvalid(),
无效吨位不超过5.5吨,
InvalidTonts\u notmultipleof5.isvalid()
);
}

这或多或少是我猜我必须要做的。我想对于我的行为,我只需要钳制。因此,如果它们提供其他值也可以,但是任何大于100的值都会钳制为100。它不需要依赖类型,这些类型用于链接符号(表示运行时值)要键入参数值,并且稍微复杂一点。艾达没有依赖类型,但却让您定义了这样的自定义积分(内置在语言中),C++具有非类型模板参数,以达到类似的效果。@ MatthieuM。谢谢。这个概念有一个通用的名称吗?当我在它前面跑过的时候,我被告知它是。“依赖型”。我想知道真实的名字(如果有一个)。@ SePMeM:如果有一个,我不知道。在C++中,它们被称为非类型模板参数,这是语言特有的…@ VabeleSelpkopiou.这是通过RIST的模块系统解决的。把代码>年龄< /代码>放在模块内,不要使字段公开。
pub trait Validator{
    fn isvalid(&self) -> bool;
}

pub struct TotalRobotTonnage{
    pub tonnage: u8,
}

impl Validator for TotalRobotTonnage{
    //is in range 20-100 and a multiple of 5
    fn isvalid(&self) -> bool{
        if self.tonnage < 20 || self.tonnage > 100 ||  self.tonnage % 5 != 0{
            false
        }else{
            true
        }
    } 
}

fn main() {
    let validtonnage = TotalRobotTonnage{tonnage: 100};
    let invalidtonnage_outofrange = TotalRobotTonnage{tonnage: 10};
    let invalidtonnage_notmultipleof5 = TotalRobotTonnage{tonnage: 21};
    println!("value {} [{}] value {} [{}] value {} [{}]", 
    validtonnage.tonnage, 
    validtonnage.isvalid(),
    invalidtonnage_outofrange.tonnage, 
    invalidtonnage_outofrange.isvalid(),
    invalidtonnage_notmultipleof5.tonnage, 
    invalidtonnage_notmultipleof5.isvalid()
);
}