英文:
Trait object as associated type of a trait object
问题
I can provide the translated code part as requested:
我编写了两个实现共同特征 `Solve` 的结构体。`Solve` 具有与特质绑定 `Display` 的关联类型 `Answer`。我希望函数 `create_solver` 返回 `Solve` 的特质对象。
我需要帮助编写关联类型 `Answer = ??`。
```rust
use std::fmt::Display;
fn main() {
let solver = create_solver(2);
let answer = solver.solve();
println!("{}", 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;
fn solve(&self) -> Self::Answer;
}
struct SolverOne;
impl Solve for SolverOne {
type Answer = u32;
fn solve(&self) -> Self::Answer {
3
}
}
struct SolverTwo;
impl Solve for SolverTwo {
type Answer = String;
fn solve(&self) -> Self::Answer {
String::from("three")
}
}
我尝试设置 Answer = Box<dyn Display>
,但导致错误。
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;
fn solve(&self) -> Self::Answer;
}
struct SolverOne;
impl Solve for SolverOne {
type Answer = Box<u32>;
fn solve(&self) -> Self::Answer {
Box::new(3)
}
}
struct SolverTwo;
impl Solve for SolverTwo {
type Answer = Box<String>;
fn solve(&self) -> Self::Answer {
Box::new(String::from("three"))
}
}
错误消息:
error[E0271]: 类型不匹配,解析为 `<SolverOne as Solve>::Answer == Box<(dyn Display + 'static)>`
--> src/main.rs:13:14
|
13 | 1 => Box::new(SolverOne),
| ^^^^^^^^^^^^^^^^^^^ 类型不匹配,解析为 `<SolverOne as Solve>::Answer == Box<(dyn Display + 'static)>`
|
注意: 预期为 `Box<(dyn std::fmt::Display + 'static)>`
--> src/main.rs:28:19
|
28 | type Answer = Box<u32>;
| ^^^^^^^^
= 注意: 预期的结构是 `Box<(dyn std::fmt::Display + 'static)>`
找到的结构是 `Box<u32>`
= 注意: 需要将 `SolverOne` 转换为对象类型 `dyn Solve<Answer = Box<(dyn std::fmt::Display + 'static)>>`
error[E0271]: 类型不匹配,解析为 `<SolverTwo as Solve>::Answer == Box<(dyn Display + 'static)>`
--> src/main.rs:12:5
|
12 | / match kind {
13 | | 1 => Box::new(SolverOne),
14 | | 2 => Box::new(SolverTwo),
15 | | _ => unreachable!()
16 | | }
| |_____^ 类型不匹配,解析为 `<SolverTwo as Solve>::Answer == Box<(dyn Display + 'static)>`
|
注意: 预期为 `Box<(dyn std::fmt::Display + 'static)>`
--> src/main.rs:38:19
|
38 | type Answer = Box<String>;
| ^^^^^^^^^^^
= 注意: 预期的结构是 `Box<(dyn std::fmt::Display + 'static)>`
找到的结构是 `Box<String>`
= 注意: 需要将 `SolverTwo` 转换为对象类型 `dyn Solve<Answer = Box<(dyn std::fmt::Display + 'static)>>`
有关此错误的更多信息,请尝试 `rustc --explain E0271`
您应该将 Answer =
设置为什么,以使其正常工作?
请注意,您要求翻译的代码片段可能包含代码错误或不完整的信息。因此,我无法为您提供完整的解决方案,但您需要将 `Answer` 设置为与实际返回类型匹配的类型,这可以是 `u32` 或 `String`,而不是 `Box<dyn Display>`。如果有其他问题,请提供更多详细信息,以便我可以提供更具体的帮助。
<details>
<summary>英文:</summary>
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`.
I need help with writing the associate type `Answer = ??`.
use std::fmt::Display;
fn main() {
let solver = create_solver(2);
let answer = solver.solve();
println!("{}", 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;
fn solve(&self) -> Self::Answer;
}
struct SolverOne;
impl Solve for SolverOne {
type Answer = u32;
fn solve(&self) -> Self::Answer {
3
}
}
struct SolverTwo;
impl Solve for SolverTwo {
type Answer = String;
fn solve(&self) -> Self::Answer {
String::from("three")
}
}
I tried setting `Answer = Box<dyn Display>` 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;
fn solve(&self) -> Self::Answer;
}
struct SolverOne;
impl Solve for SolverOne {
type Answer = Box<u32>;
fn solve(&self) -> Self::Answer {
Box::new(3)
}
}
struct SolverTwo;
impl Solve for SolverTwo {
type Answer = Box<String>;
fn solve(&self) -> Self::Answer {
Box::new(String::from("three"))
}
}
Error message:
error[E0271]: type mismatch resolving <SolverOne as Solve>::Answer == Box<(dyn Display + 'static)>
--> src/main.rs:13:14
|
13 | 1 => Box::new(SolverOne),
| ^^^^^^^^^^^^^^^^^^^ type mismatch resolving <SolverOne as Solve>::Answer == Box<(dyn Display + 'static)>
|
note: expected this to be Box<(dyn std::fmt::Display + 'static)>
--> src/main.rs:28:19
|
28 | type Answer = Box<u32>;
| ^^^^^^^^
= note: expected struct Box<(dyn std::fmt::Display + 'static)>
found struct Box<u32>
= note: required for the cast from SolverOne
to the object type dyn Solve<Answer = Box<(dyn std::fmt::Display + 'static)>>
error[E0271]: type mismatch resolving <SolverTwo as Solve>::Answer == Box<(dyn Display + 'static)>
--> src/main.rs:12:5
|
12 | / match kind {
13 | | 1 => Box::new(SolverOne),
14 | | 2 => Box::new(SolverTwo),
15 | | _ => unreachable!()
16 | | }
| |_____^ type mismatch resolving <SolverTwo as Solve>::Answer == Box<(dyn Display + 'static)>
|
note: expected this to be Box<(dyn std::fmt::Display + 'static)>
--> src/main.rs:38:19
|
38 | type Answer = Box<String>;
| ^^^^^^^^^^^
= note: expected struct Box<(dyn std::fmt::Display + 'static)>
found struct Box<String>
= note: required for the cast from SolverTwo
to the object type dyn Solve<Answer = Box<(dyn std::fmt::Display + 'static)>>
For more information about this error, try rustc --explain E0271
What should I set as `Answer = ` to make this work?
</details>
# 答案1
**得分**: 2
以下是要翻译的内容:
关联类型必须对所有返回的类型相同,而您没有这样的关联类型。但您可以创建一个使用类型擦除返回 `Box<dyn Display>` 的包装类型:
```rust
fn create_solver(kind: u32) -> Box<dyn Solve<Answer = Box<dyn Display>> {
struct ErasedSolver<T>(T);
impl<T: Solve> Solve for ErasedSolver<T>
where
T::Answer: 'static,
{
type Answer = Box<dyn Display>;
fn solve(&self) -> Self::Answer {
Box::new(self.0.solve())
}
}
match kind {
1 => Box::new(ErasedSolver(SolverOne)),
2 => Box::new(ErasedSolver(SolverTwo)),
_ => unreachable!(),
}
}
英文:
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<dyn Display>
:
fn create_solver(kind: u32) -> Box<dyn Solve<Answer = Box<dyn Display>>> {
struct ErasedSolver<T>(T);
impl<T: Solve> Solve for ErasedSolver<T>
where
T::Answer: 'static,
{
type Answer = Box<dyn Display>;
fn solve(&self) -> Self::Answer {
Box::new(self.0.solve())
}
}
match kind {
1 => Box::new(ErasedSolver(SolverOne)),
2 => Box::new(ErasedSolver(SolverTwo)),
_ => unreachable!(),
}
}
答案2
得分: 0
以下是代码部分的翻译:
这几乎是与[使Clone对象安全][1]相同的问题,为此有[`dyn-clone`][2]。您可以通过创建另一个trait和一个全局impl来在这里执行相同的操作:
trait SolveBoxed {
fn solve_boxed(&self) -> Box<dyn Display>;
}
impl<T, D> SolveBoxed for T
where
T: Solve<Answer = D>,
D: Display + 'static,
{
fn solve_boxed(&self) -> Box<dyn Display> {
Box::new(self.solve())
}
}
完整代码:(playground)
use std::fmt::Display;
fn main() {
let solver = create_solver(2);
let answer = solver.solve_boxed();
println!("{}", answer);
}
fn create_solver(kind: u32) -> Box<dyn SolveBoxed> {
match kind {
1 => Box::new(SolverOne),
2 => Box::new(SolverTwo),
_ => unreachable!(),
}
}
trait SolveBoxed {
fn solve_boxed(&self) -> Box<dyn Display>;
}
impl<T, D> SolveBoxed for T
where
T: Solve<Answer = D>,
D: Display + 'static,
{
fn solve_boxed(&self) -> Box<dyn Display> {
Box::new(self.solve())
}
}
trait Solve {
type Answer: Display;
fn solve(&self) -> Self::Answer;
}
struct SolverOne;
impl Solve for SolverOne {
type Answer = u32;
fn solve(&self) -> Self::Answer {
3
}
}
struct SolverTwo;
impl Solve for SolverTwo {
type Answer = String;
fn solve(&self) -> Self::Answer {
String::from("three")
}
}
<details>
<summary>英文:</summary>
This is almost the same problem as [making Clone object-safe][1], for which there's [`dyn-clone`][2]. You can do the same thing here by making another trait and a blanket impl:
```rs
trait SolveBoxed {
fn solve_boxed(&self) -> Box<dyn Display>;
}
impl<T, D> SolveBoxed for T
where
T: Solve<Answer = D>,
D: Display + 'static,
{
fn solve_boxed(&self) -> Box<dyn Display> {
Box::new(self.solve())
}
}
Full code: (playground)
use std::fmt::Display;
fn main() {
let solver = create_solver(2);
let answer = solver.solve_boxed();
println!("{}", answer);
}
fn create_solver(kind: u32) -> Box<dyn SolveBoxed> {
match kind {
1 => Box::new(SolverOne),
2 => Box::new(SolverTwo),
_ => unreachable!(),
}
}
trait SolveBoxed {
fn solve_boxed(&self) -> Box<dyn Display>;
}
impl<T, D> SolveBoxed for T
where
T: Solve<Answer = D>,
D: Display + 'static,
{
fn solve_boxed(&self) -> Box<dyn Display> {
Box::new(self.solve())
}
}
trait Solve {
type Answer: Display;
fn solve(&self) -> Self::Answer;
}
struct SolverOne;
impl Solve for SolverOne {
type Answer = u32;
fn solve(&self) -> Self::Answer {
3
}
}
struct SolverTwo;
impl Solve for SolverTwo {
type Answer = String;
fn solve(&self) -> Self::Answer {
String::from("three")
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论