如何约束Rust泛型仅允许指定的两类自定义Vector数据类型
泛型约束实现方案
你可以通过Rust的**标记特征(Marker Trait)**实现泛型类型限制,仅允许你指定的两类数据作为泛型参数,不需要运行时拷贝就可以直接修改内部存储的值:
- 首先定义一个空的标记特征,仅给你允许的两个类型实现该特征:
// 定义标记特征作为泛型约束的依据 pub(crate) trait LayersData {} // 给允许的两类数据实现特征 impl LayersData for Vec<Vec<Network>> {} impl LayersData for Vec<Mesh> {}
- 改写
Mapping为泛型结构体,绑定上述特征作为约束:
pub(crate) struct Mapping<T: LayersData> { layers: T } impl<T: LayersData> Mapping<T> { pub(crate) fn new(layers: T) -> Self { Mapping { layers } } } // 分别为两种泛型类型实现对应的追加方法,编译期就会做类型校验 impl Mapping<Vec<Vec<Network>>> { pub fn add_network_layer(&mut self, layer: Vec<Network>) { self.layers.push(layer); } } impl Mapping<Vec<Mesh>> { pub fn add_mesh(&mut self, mesh: Mesh) { self.layers.push(mesh); } }
该方案的所有类型校验都在编译期完成,调用对应方法不需要处理类型不匹配的错误,但要注意:Mapping<Vec<Vec<Network>>>和Mapping<Vec<Mesh>>是完全不同的类型,实例创建后泛型类型固定,不能互相转换。
Enum方案其实无需拷贝即可修改
你之前对Enum的使用存在误解,不需要拷贝就能直接修改Enum内部存储的值,只要通过模式匹配拿到内部值的可变引用即可:
impl Mapping { // 追加Network层 pub fn add_network_layer(&mut self, layer: Vec<Network>) -> Result<(), &'static str> { match &mut self.layers { NodeDefinition::NODE(layers) => { layers.push(layer); Ok(()) } _ => Err("当前实例存储的是Mesh类型,无法追加Network层") } } // 追加Mesh pub fn add_mesh(&mut self, mesh: Mesh) -> Result<(), &'static str> { match &mut self.layers { NodeDefinition::LEAF(meshes) => { meshes.push(mesh); Ok(()) } _ => Err("当前实例存储的是Network类型,无法追加Mesh") } } }
该方案的优势是同一个Mapping实例可以在运行时切换存储的类型,灵活度更高,仅需要在调用追加方法时处理可能的类型不匹配情况即可。
内容的提问来源于stack exchange,提问作者Christian Potts
相关产品推荐
相关产品推荐

