Is there type erasure of generics in Rust (like in Java) or not? I am unable to find a definitive answer.
When you use a generic function or a generic type, the compiler generates a separate instance for each distinct set of type parameters (I believe lifetime parameters are ignored, as they have no influence on the generated code). This process is called monomorphization . For instance, Vec<i32>
and Vec<String>
are different types, and therefore Vec<i32>::len()
and Vec<String>::len()
are different functions. This is necessary, because Vec<i32>
and Vec<String>
have different memory layouts, and thus need different machine code! Therefore, no , there is no type erasure.
If we use Any::type_id()
, as in the following example:
use std::any::Any;
fn main() {
let v1: Vec<i32> = Vec::new();
let v2: Vec<String> = Vec::new();
let a1 = &v1 as &dyn Any;
let a2 = &v2 as &dyn Any;
println!("{:?}", a1.type_id());
println!("{:?}", a2.type_id());
}
we obtain different type IDs for two instances of Vec
. This supports the fact that Vec<i32>
and Vec<String>
are distinct types.
However, reflection capabilities in Rust are limited; Any
is pretty much all we've got for now. You cannot obtain more information about the type of a runtime value, such as its name or its members. In order to be able to work with Any
, you must cast it (using Any::downcast_ref()
or Any::downcast_mut()
to a type that is known at compile time.
Rust does have type erasure in the form of virtual method dispatch viadyn Trait
, which allows you to have a Vec
where the elements have different concrete types:
fn main() {
let list: Vec<Box<dyn ToString>> = vec![Box::new(1), Box::new("hello")];
for item in list {
println!("{}", item.to_string());
}
}
Note that the compiler requires you to manually box the elements since it must know the size of every value at compile time. You can use a Box
, which has the same size no matter what it points to since it's just a pointer to the heap. You can also use &
-references:
fn main() {
let list: Vec<&dyn ToString> = vec![&1, &"hello"];
for item in list {
println!("{}", item.to_string());
}
}
However, note that if you use &
-references you may run into lifetime issues.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.