Rust中如何基于SlotMap生成带默认值的SecondaryMap
结论
当前slotmap官方库(最新1.0.x稳定版)并未提供原生的、可直接从SlotMap生成填充好默认值的SecondaryMap的内置方法。
现有实现优化
你自己写的基础实现逻辑是正确的,但仅支持实现了Copy trait的值类型,且不支持闭包生成值,可调整为更通用的版本:
use slotmap::{SlotMap, SecondaryMap, Key}; // 支持传入闭包生成每个值的通用版本 fn create_secondary_map<K: Key, I, V, F: FnMut() -> V>(slotmap: &SlotMap<K, I>, mut f: F) -> SecondaryMap<K, V> { // 预分配空间避免扩容开销,性能优于直接new() let mut map = SecondaryMap::with_capacity(slotmap.capacity()); slotmap.keys().for_each(|k| { map.insert(k, f()); }); map } // 传入固定默认值的重载版本 fn create_secondary_map_with_default<K: Key, I, V: Clone>(slotmap: &SlotMap<K, I>, val: V) -> SecondaryMap<K, V> { create_secondary_map(slotmap, || val.clone()) }
实现你期望的链式调用
如果要达到slotmap.create_secondary(def_value)的调用形式,可以通过为SlotMap实现扩展trait来完成:
use slotmap::{SlotMap, SecondaryMap, Key}; pub trait SlotMapSecondaryExt<K: Key, I> { /// 用固定默认值创建SecondaryMap fn create_secondary<V: Clone>(&self, val: V) -> SecondaryMap<K, V>; /// 用无参闭包生成的值创建SecondaryMap fn create_secondary_with<V, F: FnMut() -> V>(&self, f: F) -> SecondaryMap<K, V>; /// 可选扩展:支持用键和原SlotMap中的值生成新值 fn create_secondary_with_entry<V, F: FnMut(K, &I) -> V>(&self, f: F) -> SecondaryMap<K, V>; } impl<K: Key, I> SlotMapSecondaryExt<K, I> for SlotMap<K, I> { fn create_secondary<V: Clone>(&self, val: V) -> SecondaryMap<K, V> { self.create_secondary_with(|| val.clone()) } fn create_secondary_with<V, F: FnMut() -> V>(&self, mut f: F) -> SecondaryMap<K, V> { let mut map = SecondaryMap::with_capacity(self.capacity()); self.keys().for_each(|k| { map.insert(k, f()); }); map } fn create_secondary_with_entry<V, F: FnMut(K, &I) -> V>(&self, mut f: F) -> SecondaryMap<K, V> { let mut map = SecondaryMap::with_capacity(self.capacity()); self.iter().for_each(|(k, v)| { map.insert(k, f(k, v)); }); map } }
用法示例
引入上面的扩展trait后,就可以直接按你期望的方式调用:
// 用固定默认值 let secondary = slotmap.create_secondary(def_value); // 用闭包生成独立的默认值 let secondary = slotmap.create_secondary_with(|| Default::default()); // 用原SlotMap的条目生成值 let secondary = slotmap.create_secondary_with_entry(|k, v| v.some_field.clone());
内容的提问来源于stack exchange,提问作者nir shahar
相关产品推荐
相关产品推荐

