为存有Box<dyn T>的结构体实现Clone


问题描述:

无法为以下结构体实现Clone:

1
2pub trait GetName {
3 fn get_name(&self) -> String;
4}
5
6#[device(Clone)]
7struct Node{
8 name: String,
9 children: Vec<Box<dyn GetName>>
10}

参考链接

stackoverflow how-to-clone-a-struct-storing-a-boxed-trait-object

具体实现

1// 先为GetName继承一个能clone的trait
2pub trait GetName: NodeClone{
3 fn get_name(&self) -> String;
4}
5
6//自定义一个clone,里面套默认clone
7pub trait NodeClone {
8 fn clone_box(&self) -> Box<dyn GetName>;
9}
10
11//自定义clone接口,where限制这个NodeClone只是用在GetName上,
12//如果不借助这个NodeClone,直接pub tarit GetName:Clone{}是不行的
13//没法放在Box<>里
14impl<T> NodeClone for T
15where
16 T: 'static + GetName + Clone,
17{
18 fn clone_box(&self) -> Box<dyn GetName> {
19 Box::new(self.clone())
20 }
21}
22
23
24//为Box<dyn T>实现Clone,调用dyn GetName的自定义Clone
25impl Clone for Box<dyn GetName> {
26 fn clone(&self) -> Box<dyn GetName> {
27 self.clone_box()
28 }
29}
30
31#[derive(Clone)]
32pub struct Node {
33 name: String,
34 children: Vec<Box<dyn GetName>>//子元素只要能GetName就可以
35}
36
37impl GetName for Node{
38 fn get_name(&self) -> String{
39 return self.name.clone();
40 }
41}
42
43impl Node{
44 //将子元素的name拼起来打印
45 pub fn print_children(&self)->String{
46 let s = self.children.iter()
47 .map(|n|n.get_name())
48 .collect::<Vec<_>>()
49 .join(",");
50 format!("[{}]",s)
51 }
52}
53
54fn main() {
55
56 let a1= Box::new(Node{
57 name: "a1111".to_string(),
58 children:vec![]
59 });
60 let a2= Box::new(Node{
61 name: "a2".to_string(),
62 children:vec![]
63 });
64
65 let b = Node{
66 name: "bbb".to_string(),
67 //测试一下,to_vec()会调用每个元素的Clone
68 //a1、a2具体类型是Node,具有GetName、Clone接口,
69 children:[a1 as Box<dyn GetName>,a2 as Box<dyn GetName>].to_vec()
70 };
71
72 println!("b={}",b.print_children());
73
74
75}