问题
In rust 1.0.0-nightly, this code works fine:
fn main() {
let x = 10f64;
let y = 20f64;
let z = x + y;
println!("z = {}", z);
}
But if I try to use a newtype (according to the rust book):
struct Metres(f64);
fn main() {
let x = Metres(10f64);
let y = Metres(20f64);
let z = x + y;
println!("z = {}", z);
}
I get this compiler error:
test.rs:6:13: 6:18 error: binary operation `+` cannot be applied to type `Metres`
test.rs:6 let z = x + y;
^~~~~
error: aborting due to previous error
Since Metres
is basically a f64
, why can't the compiler use the same +
operator, and create a new Metres
object for z
?
How can I use newtypes if I can't do simple things like adding and such? How are they "very useful" (as the book calls them)?
(There is an old question about this, but rust changes a lot, hence I'm reasking)
回答1:
The reason newtypes work this way is generally because you want to avoid the traits defined on the underlying type. For example, you could have Metres
and Feet
which both wrap f64
but define addition of Metres
and Feet
to do unit conversion, which plain f64
addition doesn't give you.
Of course, sometimes you do want the underlying trait implementation. Currently, you'd have to write a wrapper implementation yourself, but there is an RFC for the ability to generate these automatically: https://github.com/rust-lang/rfcs/issues/479
回答2:
As mentioned by Scott Olson, it is actually voluntary that newtypes do not "degenerate" in their only attribute. They are here to introduce a new type, after all.
If all you want is a synonym, which is slightly different, then you can use a type alias instead:
type Metres = f64;
However, you then lose the benefits of a new type:
type Grams = f64;
fn main() {
let m = 10 as Metres;
let g = 5 as Grams;
println!("{}", m + g); // prints 15, see http://is.gd/IdYOEg
}
来源:https://stackoverflow.com/questions/28252038/why-dont-newtypes-use-the-traits-from-the-inner-type