I have a struct which holds an Arc
of a dynamic trait object.
For convenience, I want to have a constructor which either takes a struct and turns that into an Arc
or directly takes an Arc
. However, I haven't found a way which satisfies the compiler.
Minimal example:
use std::sync::Arc;
trait Shape { }
struct Sphere;
impl Shape for Sphere { }
struct Mesh {
shape: Arc<dyn Shape>,
}
impl Mesh {
fn new(shape: impl Into<Arc<dyn Shape>>) -> Self {
Mesh { shape: shape.into() }
}
}
fn main() {
let _ = Mesh::new(Sphere);
let _ = Mesh::new(Arc::new(Sphere));
}
You'll want to make new
take in anything that implements Shape
, then internally wrap that in an Arc
. You can do this by either using impl Shape
as type, or with a generic type T
with a bound T: Shape
. You'll also need to include a 'static
bound, since a Arc<dyn Shape>
implies that the contained type is 'static
.
use std::sync::Arc;
trait Shape { }
struct Sphere;
impl Shape for Sphere { }
struct Mesh {
shape: Arc<dyn Shape>,
}
impl Mesh {
fn new(shape: impl Shape + 'static) -> Self {
Mesh { shape: Arc::new(shape) }
}
fn new_v2<T: Shape + 'static>(shape: T) -> Self {
Mesh { shape: Arc::new(shape) }
}
}
fn main() {
let _ = Mesh::new(Sphere);
let _ = Mesh::new_v2(Sphere);
}
If you want to support impl Shape
, Arc<impl Shape>
, and perhaps also Arc<dyn Shape>
arguments, you can create your own trait
trait IntoArcDynShape {
fn into_arc_dyn_shape(self) -> Arc<dyn Shape>;
}
impl<T: Shape + 'static> IntoArcDynShape for T {
fn into_arc_dyn_shape(self) -> Arc<dyn Shape> {
Arc::new(self)
}
}
impl<T: Shape + 'static> IntoArcDynShape for Arc<T> {
fn into_arc_dyn_shape(self) -> Arc<dyn Shape> {
self
}
}
impl IntoArcDynShape for Arc<dyn Shape> {
fn into_arc_dyn_shape(self) -> Arc<dyn Shape> {
self
}
}
Rust Playground
Note however that this does prevent you from implementing Shape
for Arc<…>
itself.
conqp
September 13, 2024, 8:55pm
4
What about just implementing From
?
1 Like
This does, however, not work when I already have an Arc
and want to supply it to the constructor.
(Updated the example to include that case)
Thanks, but in my actual code, the struct holds two Arc
s, so I would need to implement all combinations manually, which I'd rather not do.
Thanks, that's exactly what I'm looking for. I'm not a huge fan of creating an extra trait for it, but I guess I'll have to work with it.
system
Closed
December 13, 2024, 1:05pm
8
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.