4 ms·
Note that `from` and `try_from` are generally preferred to using `as`, where possible. This also allows casting between non-primitive types. https://doc.rust-l
by ChrisSD 5y ago
Note that `from` and `try_from` are generally preferred to using `as`, where possible. This also allows casting between non-primitive types.
https://doc.rust-lang.org/std/convert/trait.TryFrom.html#examples https://doc.rust-lang.org/std/convert/trait.TryFrom.html#exa...
- xvedejas 5y agoHow expensive is this kind of casting in Rust? Like, if I have a struct which has a superset of attributes that I need for the type I'm casting to, do I need to construct a new struct instance just to have something to treat as my target type, or is there a simpler way that doesn't involve new allocation?
- msbarnett 5y agoYou have options. Given Superset struct A, some other struct B that happens to have a subset of A’s fields, and some function foo which takes an argument of type B, you could 1) implement From<A> for B, and use that to convert instances of A when you want to call foo. This would probably involve some copying and/or allocation. 2) back up and turn foo into something that takes a trait argument instead. Now instead of taking instances of A, what it needs struct to provide is defined by a trait, which you can provide implementations of for both A and B. Now you can pass either to foo. 3) potentially, depending on the layout of structs, create a union and do some type punning to convert between them. this requires unsafe and you’d better be right about the struct layouts. 4) just make foo take a tagged union of the two structs. this isn’t unsafe but has different storage tradeoffs. also foo would need to handle each case separately. 5) find some other way to skin this cat. there’s plenty #2 would be idiomatic in most circumstances I think?
- rackjack 5y agoYeah, I would do (2) if possible. ``` struct Person { name: String, } struct Engineer { name: String, boss: String, } trait Name { fn get_name(&self) -> &str; } impl Name for Person { ... } impl Name for Engineer { ... } ```
- kd5bjo 5y ago6) Instead of having common fields, make A contain an instance of B. Then, implement `AsRef<B> for A`.
- herbstein 5y ago> How expensive is this kind of casting in Rust? It really depends on how you're implementing it. If you're doing a clone/deepcopy-style conversion, or if you're consuming the value you're casting from. However, since most values in Rust are placed on the stack, "allocating" them is incredibly cheap. Moving them around is often also cheap, and involves just a few `mov`s from registers to registers, or stack-address to stack-address. A very simple example: https://godbolt.org/z/WMePqMd71 https://godbolt.org/z/WMePqMd71