Let's say 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?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
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);
println!("{}, {}", std::mem::size_of::<Age>(), std::mem::size_of::<u16>());
}
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.
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.