4 ms·
I can agree with the initial frustration coming from a GC-ed language until one figures out the right way to design code and structure data in a language with m
by ehsanu1 9y ago
I can agree with the initial frustration coming from a GC-ed language until one figures out the right way to design code and structure data in a language with manual memory management. But I got over it eventually.
I'm also curious about this nitty gritty bit. I see this:
Generally, Self : Sized is used to indicate that the trait should not be used as a trait object. If the trait comes from your own crate, consider removing this restriction.
I guess you needed that sized restriction for some reason, assuming this was a trait of your own?
- SCdF 9y agoYeah. So I'm following a ray tracing book that uses C++ as example code, and am using Traits as a form of interface: there is a trait of Material that has a function on it, and then there are different "implementations" of Material with different implementations of that fn, and can have arbitrary data stored against them. I need to have them sized because I need to copy them at a point where I only understand they are a Material and not what the actual struct are, and I need to do this because I can't get a reference to work in this instance due to the fun of lifetimes. AFAICT the way to do this without Traits in Rust would be to have an enum, and then have an external function that takes the enum, matches against it and runs different code depending. To me the second one is kind of gross, but I may just go with it, or just give up and do something else.
- tangent128 9y agoWould it work to add a boxed_clone() function to your Material trait that returns a Box<Material>? (or create a BoxedClone trait if you need that pattern more generally) Implementations of boxed_clone() could still use &self.clone() to limit boilerplate. Alternatively, if the Materials are not going to be modified and you just need multiple references to the same object, you could replace the Box<> with an Rc<> or Arc<>.
- comex 9y agoYep, those are the best approaches. For the former, you might consider the 'objekt' crate, which avoids the boilerplate: https://docs.rs/objekt/0.1.0/objekt/ https://docs.rs/objekt/0.1.0/objekt/
- physguy1123 9y ago> there is a trait of Material that has a function on it, and then there are different "implementations" of Material with different implementations of that fn, and can have arbitrary data stored against them. Do you mean like a class hierarchy+virtual functions, or just having allocated data of arbitrary length past the end of a struct? If it's the former, C++ fares no better in this regard but it's pretty easy to do in Rust. You just have a cloner in the interface. If it's the latter, that's pretty nonstandard and Rust doesn't make that easy for good reason. Unless this raytracer is doing something wild the code should hopefully be refactorable into a more normal struct+trait layout.
- SCdF 9y agoimpl Material for Lambertain { ... fn box_clone(&self) -> Box<Material> { Box::new(Lambertian { ..self }) } } Holllllly shit I think that works. Why am I allowed to do this and not just derive Clone and Copy!?!
- physguy1123 9y agoCopy and clone have specific meanings and must resolve to the type of the class itself - basically copy or cloning a class of type A gets you another class of type A always. It's possible, from a language sense, to have an implementation of box that could directly clone the trait, but I don't believe it would have a reasonable api.