最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

rust - Remove `Sized` bound from trait whose method takes reference to implementor`<Self>` as an arg - Stack Overf

programmeradmin4浏览0评论

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 Using Self in Interp1D<Self> makes the method itself dyn-incompatible, it must "Be a method that does not use Self except in the type of the receiver." and interpolator is not the receiver. – cafce25 Commented Mar 6 at 21:34
  • @cafce25 Ah, that's unfortunate. Thanks for the reference; I'm new to dynamic dispatch.. can ya tell? If you submit this as an answer, I'll accept it. – Kyle Carow Commented Mar 6 at 22:10
  • I was able to make the trait dyn-compatible by creating a separate struct for the interpolation data, so no need for the Self in the method – Kyle Carow Commented Mar 7 at 1:22
Add a comment  | 

1 Answer 1

Reset to default 0

I 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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论