Trait object as associated type of a trait object.

huangapple go评论100阅读模式
英文:

Trait object as associated type of a trait object

问题

I can provide the translated code part as requested:

  1. 我编写了两个实现共同特征 `Solve` 的结构体。`Solve` 具有与特质绑定 `Display` 的关联类型 `Answer`。我希望函数 `create_solver` 返回 `Solve` 的特质对象。
  2. 我需要帮助编写关联类型 `Answer = ??`
  3. ```rust
  4. use std::fmt::Display;
  5. fn main() {
  6. let solver = create_solver(2);
  7. let answer = solver.solve();
  8. println!("{}", answer);
  9. }
  10. fn create_solver(kind: u32) -> Box<dyn Solve<Answer = ??>> {
  11. match kind {
  12. 1 => Box::new(SolverOne),
  13. 2 => Box::new(SolverTwo),
  14. _ => unreachable!()
  15. }
  16. }
  17. trait Solve {
  18. type Answer: Display;
  19. fn solve(&self) -> Self::Answer;
  20. }
  21. struct SolverOne;
  22. impl Solve for SolverOne {
  23. type Answer = u32;
  24. fn solve(&self) -> Self::Answer {
  25. 3
  26. }
  27. }
  28. struct SolverTwo;
  29. impl Solve for SolverTwo {
  30. type Answer = String;
  31. fn solve(&self) -> Self::Answer {
  32. String::from("three")
  33. }
  34. }

我尝试设置 Answer = Box<dyn Display>,但导致错误。

  1. fn create_solver(kind: u32) -> Box<dyn Solve<Answer = Box<dyn Display>>> {
  2. match kind {
  3. 1 => Box::new(SolverOne),
  4. 2 => Box::new(SolverTwo),
  5. _ => unreachable!()
  6. }
  7. }
  8. trait Solve {
  9. type Answer: Display;
  10. fn solve(&self) -> Self::Answer;
  11. }
  12. struct SolverOne;
  13. impl Solve for SolverOne {
  14. type Answer = Box<u32>;
  15. fn solve(&self) -> Self::Answer {
  16. Box::new(3)
  17. }
  18. }
  19. struct SolverTwo;
  20. impl Solve for SolverTwo {
  21. type Answer = Box<String>;
  22. fn solve(&self) -> Self::Answer {
  23. Box::new(String::from("three"))
  24. }
  25. }

错误消息:

  1. error[E0271]: 类型不匹配,解析为 `<SolverOne as Solve>::Answer == Box<(dyn Display + 'static)>`
  2. --> src/main.rs:13:14
  3. |
  4. 13 | 1 => Box::new(SolverOne),
  5. | ^^^^^^^^^^^^^^^^^^^ 类型不匹配,解析为 `<SolverOne as Solve>::Answer == Box<(dyn Display + 'static)>`
  6. |
  7. 注意: 预期为 `Box<(dyn std::fmt::Display + 'static)>`
  8. --> src/main.rs:28:19
  9. |
  10. 28 | type Answer = Box<u32>;
  11. | ^^^^^^^^
  12. = 注意: 预期的结构是 `Box<(dyn std::fmt::Display + 'static)>`
  13. 找到的结构是 `Box<u32>`
  14. = 注意: 需要将 `SolverOne` 转换为对象类型 `dyn Solve<Answer = Box<(dyn std::fmt::Display + 'static)>>`
  15. error[E0271]: 类型不匹配,解析为 `<SolverTwo as Solve>::Answer == Box<(dyn Display + 'static)>`
  16. --> src/main.rs:12:5
  17. |
  18. 12 | / match kind {
  19. 13 | | 1 => Box::new(SolverOne),
  20. 14 | | 2 => Box::new(SolverTwo),
  21. 15 | | _ => unreachable!()
  22. 16 | | }
  23. | |_____^ 类型不匹配,解析为 `<SolverTwo as Solve>::Answer == Box<(dyn Display + 'static)>`
  24. |
  25. 注意: 预期为 `Box<(dyn std::fmt::Display + 'static)>`
  26. --> src/main.rs:38:19
  27. |
  28. 38 | type Answer = Box<String>;
  29. | ^^^^^^^^^^^
  30. = 注意: 预期的结构是 `Box<(dyn std::fmt::Display + 'static)>`
  31. 找到的结构是 `Box<String>`
  32. = 注意: 需要将 `SolverTwo` 转换为对象类型 `dyn Solve<Answer = Box<(dyn std::fmt::Display + 'static)>>`
  33. 有关此错误的更多信息,请尝试 `rustc --explain E0271`

您应该将 Answer = 设置为什么,以使其正常工作?

  1. 请注意,您要求翻译的代码片段可能包含代码错误或不完整的信息。因此,我无法为您提供完整的解决方案,但您需要将 `Answer` 设置为与实际返回类型匹配的类型,这可以是 `u32` `String`,而不是 `Box<dyn Display>`。如果有其他问题,请提供更多详细信息,以便我可以提供更具体的帮助。
  2. <details>
  3. <summary>英文:</summary>
  4. I wrote two structs that implement a common trait `Solve`. `Solve` has an associated type `Answer` with trait bound `Display`. I want the function `create_solver` to return a trait object of `Solve`.
  5. I need help with writing the associate type `Answer = ??`.

use std::fmt::Display;

fn main() {
let solver = create_solver(2);

  1. let answer = solver.solve();
  2. println!(&quot;{}&quot;, answer);

}

fn create_solver(kind: u32) -> Box<dyn Solve<Answer = ??>> {
match kind {
1 => Box::new(SolverOne),
2 => Box::new(SolverTwo),
_ => unreachable!()
}
}

trait Solve {
type Answer: Display;

  1. fn solve(&amp;self) -&gt; Self::Answer;

}

struct SolverOne;

impl Solve for SolverOne {
type Answer = u32;

  1. fn solve(&amp;self) -&gt; Self::Answer {
  2. 3
  3. }

}

struct SolverTwo;

impl Solve for SolverTwo {
type Answer = String;

  1. fn solve(&amp;self) -&gt; Self::Answer {
  2. String::from(&quot;three&quot;)
  3. }

}

  1. I tried setting `Answer = Box&lt;dyn Display&gt;` but that results in error.

fn create_solver(kind: u32) -> Box<dyn Solve<Answer = Box<dyn Display>>> {
match kind {
1 => Box::new(SolverOne),
2 => Box::new(SolverTwo),
_ => unreachable!()
}
}

trait Solve {
type Answer: Display;

  1. fn solve(&amp;self) -&gt; Self::Answer;

}

struct SolverOne;

impl Solve for SolverOne {
type Answer = Box<u32>;

  1. fn solve(&amp;self) -&gt; Self::Answer {
  2. Box::new(3)
  3. }

}

struct SolverTwo;

impl Solve for SolverTwo {
type Answer = Box<String>;

  1. fn solve(&amp;self) -&gt; Self::Answer {
  2. Box::new(String::from(&quot;three&quot;))
  3. }

}

  1. Error message:

error[E0271]: type mismatch resolving &lt;SolverOne as Solve&gt;::Answer == Box&lt;(dyn Display + &#39;static)&gt;
--> src/main.rs:13:14
|
13 | 1 => Box::new(SolverOne),
| ^^^^^^^^^^^^^^^^^^^ type mismatch resolving &lt;SolverOne as Solve&gt;::Answer == Box&lt;(dyn Display + &#39;static)&gt;
|
note: expected this to be Box&lt;(dyn std::fmt::Display + &#39;static)&gt;
--> src/main.rs:28:19
|
28 | type Answer = Box<u32>;
| ^^^^^^^^
= note: expected struct Box&lt;(dyn std::fmt::Display + &#39;static)&gt;
found struct Box&lt;u32&gt;
= note: required for the cast from SolverOne to the object type dyn Solve&lt;Answer = Box&lt;(dyn std::fmt::Display + &#39;static)&gt;&gt;

error[E0271]: type mismatch resolving &lt;SolverTwo as Solve&gt;::Answer == Box&lt;(dyn Display + &#39;static)&gt;
--> src/main.rs:12:5
|
12 | / match kind {
13 | | 1 => Box::new(SolverOne),
14 | | 2 => Box::new(SolverTwo),
15 | | _ => unreachable!()
16 | | }
| |_____^ type mismatch resolving &lt;SolverTwo as Solve&gt;::Answer == Box&lt;(dyn Display + &#39;static)&gt;
|
note: expected this to be Box&lt;(dyn std::fmt::Display + &#39;static)&gt;
--> src/main.rs:38:19
|
38 | type Answer = Box<String>;
| ^^^^^^^^^^^
= note: expected struct Box&lt;(dyn std::fmt::Display + &#39;static)&gt;
found struct Box&lt;String&gt;
= note: required for the cast from SolverTwo to the object type dyn Solve&lt;Answer = Box&lt;(dyn std::fmt::Display + &#39;static)&gt;&gt;

For more information about this error, try rustc --explain E0271

  1. What should I set as `Answer = ` to make this work?
  2. </details>
  3. # 答案1
  4. **得分**: 2
  5. 以下是要翻译的内容:
  6. 关联类型必须对所有返回的类型相同,而您没有这样的关联类型。但您可以创建一个使用类型擦除返回 `Box<dyn Display>` 的包装类型:
  7. ```rust
  8. fn create_solver(kind: u32) -> Box<dyn Solve<Answer = Box<dyn Display>> {
  9. struct ErasedSolver<T>(T);
  10. impl<T: Solve> Solve for ErasedSolver<T>
  11. where
  12. T::Answer: 'static,
  13. {
  14. type Answer = Box<dyn Display>;
  15. fn solve(&self) -> Self::Answer {
  16. Box::new(self.0.solve())
  17. }
  18. }
  19. match kind {
  20. 1 => Box::new(ErasedSolver(SolverOne)),
  21. 2 => Box::new(ErasedSolver(SolverTwo)),
  22. _ => unreachable!(),
  23. }
  24. }
英文:

The associated type has to be the same for all types returned, and you have no such associated type. But you can create a wrapper type that using type erasure returns Box&lt;dyn Display&gt;:

  1. fn create_solver(kind: u32) -&gt; Box&lt;dyn Solve&lt;Answer = Box&lt;dyn Display&gt;&gt;&gt; {
  2. struct ErasedSolver&lt;T&gt;(T);
  3. impl&lt;T: Solve&gt; Solve for ErasedSolver&lt;T&gt;
  4. where
  5. T::Answer: &#39;static,
  6. {
  7. type Answer = Box&lt;dyn Display&gt;;
  8. fn solve(&amp;self) -&gt; Self::Answer {
  9. Box::new(self.0.solve())
  10. }
  11. }
  12. match kind {
  13. 1 =&gt; Box::new(ErasedSolver(SolverOne)),
  14. 2 =&gt; Box::new(ErasedSolver(SolverTwo)),
  15. _ =&gt; unreachable!(),
  16. }
  17. }

答案2

得分: 0

以下是代码部分的翻译:

  1. 这几乎是与[使Clone对象安全][1]相同的问题,为此有[`dyn-clone`][2]。您可以通过创建另一个trait和一个全局impl来在这里执行相同的操作
  2. trait SolveBoxed {
  3. fn solve_boxed(&self) -> Box<dyn Display>;
  4. }
  5. impl<T, D> SolveBoxed for T
  6. where
  7. T: Solve<Answer = D>,
  8. D: Display + 'static,
  9. {
  10. fn solve_boxed(&self) -> Box<dyn Display> {
  11. Box::new(self.solve())
  12. }
  13. }

完整代码:(playground)

  1. use std::fmt::Display;
  2. fn main() {
  3. let solver = create_solver(2);
  4. let answer = solver.solve_boxed();
  5. println!("{}", answer);
  6. }
  7. fn create_solver(kind: u32) -> Box<dyn SolveBoxed> {
  8. match kind {
  9. 1 => Box::new(SolverOne),
  10. 2 => Box::new(SolverTwo),
  11. _ => unreachable!(),
  12. }
  13. }
  14. trait SolveBoxed {
  15. fn solve_boxed(&self) -> Box<dyn Display>;
  16. }
  17. impl<T, D> SolveBoxed for T
  18. where
  19. T: Solve<Answer = D>,
  20. D: Display + 'static,
  21. {
  22. fn solve_boxed(&self) -> Box<dyn Display> {
  23. Box::new(self.solve())
  24. }
  25. }
  26. trait Solve {
  27. type Answer: Display;
  28. fn solve(&self) -> Self::Answer;
  29. }
  30. struct SolverOne;
  31. impl Solve for SolverOne {
  32. type Answer = u32;
  33. fn solve(&self) -> Self::Answer {
  34. 3
  35. }
  36. }
  37. struct SolverTwo;
  38. impl Solve for SolverTwo {
  39. type Answer = String;
  40. fn solve(&self) -> Self::Answer {
  41. String::from("three")
  42. }
  43. }
  1. <details>
  2. <summary>英文:</summary>
  3. This is almost the same problem as [making Clone object-safe][1], for which there&#39;s [`dyn-clone`][2]. You can do the same thing here by making another trait and a blanket impl:
  4. ```rs
  5. trait SolveBoxed {
  6. fn solve_boxed(&amp;self) -&gt; Box&lt;dyn Display&gt;;
  7. }
  8. impl&lt;T, D&gt; SolveBoxed for T
  9. where
  10. T: Solve&lt;Answer = D&gt;,
  11. D: Display + &#39;static,
  12. {
  13. fn solve_boxed(&amp;self) -&gt; Box&lt;dyn Display&gt; {
  14. Box::new(self.solve())
  15. }
  16. }

Full code: (playground)

  1. use std::fmt::Display;
  2. fn main() {
  3. let solver = create_solver(2);
  4. let answer = solver.solve_boxed();
  5. println!(&quot;{}&quot;, answer);
  6. }
  7. fn create_solver(kind: u32) -&gt; Box&lt;dyn SolveBoxed&gt; {
  8. match kind {
  9. 1 =&gt; Box::new(SolverOne),
  10. 2 =&gt; Box::new(SolverTwo),
  11. _ =&gt; unreachable!(),
  12. }
  13. }
  14. trait SolveBoxed {
  15. fn solve_boxed(&amp;self) -&gt; Box&lt;dyn Display&gt;;
  16. }
  17. impl&lt;T, D&gt; SolveBoxed for T
  18. where
  19. T: Solve&lt;Answer = D&gt;,
  20. D: Display + &#39;static,
  21. {
  22. fn solve_boxed(&amp;self) -&gt; Box&lt;dyn Display&gt; {
  23. Box::new(self.solve())
  24. }
  25. }
  26. trait Solve {
  27. type Answer: Display;
  28. fn solve(&amp;self) -&gt; Self::Answer;
  29. }
  30. struct SolverOne;
  31. impl Solve for SolverOne {
  32. type Answer = u32;
  33. fn solve(&amp;self) -&gt; Self::Answer {
  34. 3
  35. }
  36. }
  37. struct SolverTwo;
  38. impl Solve for SolverTwo {
  39. type Answer = String;
  40. fn solve(&amp;self) -&gt; Self::Answer {
  41. String::from(&quot;three&quot;)
  42. }
  43. }

huangapple
  • 本文由 发表于 2023年3月21日 02:07:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75793849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定