This is a 'sequel' to a previous question of mine, with a more representative example, and a different approach informed by the accepted answer.
Current code state:
- Playground link
- Repo/branch link
My lib crate provides numerical interpolation over multiple dimensionalities and interpolation strategies. The strategy of an Interp1D
instance can be changed at runtime (dynamically dispatched) by proving a different Box<dyn Strategy1D>
after instantiation.
pub struct Interp1D {
x: Vec<f64>,
f_x: Vec<f64>,
strategy: Box<dyn Strategy1D>,
}
pub trait Strategy1D {
fn interpolate(
&self,
interpolator: &Interp1D,
point: &[f64; 1],
) -> f64;
}
The question
Playground link
I want to support static dispatch to allow for better runtime performance, while still allowing users to supply a Box<dyn Strategy1D>
if they want to switch strategies at runtime.
This means my structs will have a generic for the strategy, to support static dispatch:
pub struct Interp1D<S: Strategy1D> {
x: Vec<f64>,
f_x: Vec<f64>,
strategy: S,
}
// as a consequence the trait needs to change:
pub trait Strategy1D: Sized { // the `Sized` bound here makes this dyn-incompatible
fn interpolate(
&self,
interpolator: &Interp1D<Self>, // the `Self` here requires `Sized`
point: &[f64; 1],
) -> f64;
}
Adding this:
impl Strategy1D for Box<dyn Strategy1D> {
// ^^^^^^^^^^^^^^^^^^^
// error[E0038]: the trait `Strategy1D` cannot be made into an object
fn interpolate(
&self,
interpolator: &Interp1D<Self>,
point: &[f64; 1],
) -> f64 {
// delegate to boxed thing
(**self).interpolate(struct, interpolator, point)
}
}
makes the compiler mad, Strategy1D
is not dyn-compatible due to the Sized
bound.
Is there some way to make the trait dyn-compatible? Or is it impossible, and should I just stick with my original code if I want to allow dynamic dispatch?
This is a 'sequel' to a previous question of mine, with a more representative example, and a different approach informed by the accepted answer.
Current code state:
- Playground link
- Repo/branch link
My lib crate provides numerical interpolation over multiple dimensionalities and interpolation strategies. The strategy of an Interp1D
instance can be changed at runtime (dynamically dispatched) by proving a different Box<dyn Strategy1D>
after instantiation.
pub struct Interp1D {
x: Vec<f64>,
f_x: Vec<f64>,
strategy: Box<dyn Strategy1D>,
}
pub trait Strategy1D {
fn interpolate(
&self,
interpolator: &Interp1D,
point: &[f64; 1],
) -> f64;
}
The question
Playground link
I want to support static dispatch to allow for better runtime performance, while still allowing users to supply a Box<dyn Strategy1D>
if they want to switch strategies at runtime.
This means my structs will have a generic for the strategy, to support static dispatch:
pub struct Interp1D<S: Strategy1D> {
x: Vec<f64>,
f_x: Vec<f64>,
strategy: S,
}
// as a consequence the trait needs to change:
pub trait Strategy1D: Sized { // the `Sized` bound here makes this dyn-incompatible
fn interpolate(
&self,
interpolator: &Interp1D<Self>, // the `Self` here requires `Sized`
point: &[f64; 1],
) -> f64;
}
Adding this:
impl Strategy1D for Box<dyn Strategy1D> {
// ^^^^^^^^^^^^^^^^^^^
// error[E0038]: the trait `Strategy1D` cannot be made into an object
fn interpolate(
&self,
interpolator: &Interp1D<Self>,
point: &[f64; 1],
) -> f64 {
// delegate to boxed thing
(**self).interpolate(struct, interpolator, point)
}
}
makes the compiler mad, Strategy1D
is not dyn-compatible due to the Sized
bound.
Is there some way to make the trait dyn-compatible? Or is it impossible, and should I just stick with my original code if I want to allow dynamic dispatch?
Share edited Mar 6 at 19:54 Kyle Carow asked Mar 6 at 19:43 Kyle CarowKyle Carow 3762 silver badges12 bronze badges 3 |1 Answer
Reset to default 0I was able to resolve this by changing the trait method to not take Self
, instead defining a new struct to hold the relevant data, and passing that instead.
Self
inInterp1D<Self>
makes the method itself dyn-incompatible, it must "Be a method that does not useSelf
except in the type of the receiver." andinterpolator
is not the receiver. – cafce25 Commented Mar 6 at 21:34Self
in the method – Kyle Carow Commented Mar 7 at 1:22