17 个版本 (破坏性)
0.14.0 | 2024 年 5 月 10 日 |
---|---|
0.13.0 | 2023 年 8 月 25 日 |
0.12.0 | 2023 年 6 月 10 日 |
0.11.0 | 2022 年 8 月 26 日 |
0.10.0 | 2022 年 7 月 10 日 |
#83 in 数据结构
10,392 每月下载量
用于 3 个 crate (2 直接)
130KB
2.5K SLoC
类型擦除向量。所有元素具有相同类型。
设计为尽可能类型擦除 - 大多数操作不知道具体的类型。例如,您可以将一个类型擦除向量中的项移动或复制/克隆到另一个类型擦除向量中,而不必知道它们的类型。或者您可以在类型擦除向量内部擦除、交换、移动、复制元素等...
只有类型擦除的析构和克隆操作有间接调用的额外开销。
用法
let mut vec: AnyVec = AnyVec::new::<String>();
{
// Typed operations.
let mut vec = vec.downcast_mut::<String>().unwrap();
vec.push(String::from("0"));
vec.push(String::from("1"));
vec.push(String::from("2"));
}
let mut other_vec: AnyVec = AnyVec::new::<String>();
// Fully type erased element move from one vec to another
// without intermediate mem-copies.
let element = vec.swap_remove(0);
other_vec.push(element);
// Output 2 1
for s in vec.downcast_ref::<String>().unwrap(){
println!("{}", s);
}
有关更多信息,请参阅 文档。
Send, Sync, Clone
您可以使得 AnyVec
具有可 Send
、可 Sync
和可 Clone
的能力。
use any_vec::AnyVec;
use any_vec::traits::*;
let v1: AnyVec<dyn Cloneable + Sync + Send> = AnyVec::new::<String>();
let v2 = v1.clone();
这些约束将在编译时应用于元素类型
// This will fail to compile.
let v1: AnyVec<dyn Sync + Send> = AnyVec::new::<Rc<usize>>();
不可克隆的 AnyVec
的大小比 1 个指针小。
LazyClone
尽可能情况下,any_vec
类型擦除的元素可以懒加载克隆。
let mut v1: AnyVec<dyn Cloneable> = AnyVec::new::<String>();
v1.push(AnyValueWrapper::new(String::from("0")));
let mut v2: AnyVec<dyn Cloneable> = AnyVec::new::<String>();
let e = v1.swap_remove(0);
v2.push(e.lazy_clone());
v2.push(e.lazy_clone());
MemBuilder
MemBuilder
+ Mem
对于 AnyVec
来说就像 Allocator
。但与分配器不同,Mem
的容器专用设计允许进行更多优化。例如,通过更改 MemBuilder
,可以从 AnyVec
创建堆分配的 FixedAnyVec
和小型缓冲区优化(SBO) SmallAnyVec
。
type FixedAnyVec<Traits = dyn None> = AnyVec<Traits, Stack<512>>;
let mut any_vec: FixedAnyVec = AnyVec::new::<String>();
// This will be on stack, without any allocations.
any_vec.push(AnyValueWrapper::new(String::from("0")))
借助 clone_empty_in
,您可以使用堆分配或 SBO AnyVec
作为未知类型值的快速中间存储。
fn self_push_first_element<T: Trait + Cloneable>(any_vec: &mut AnyVec<T>){
let mut tmp = any_vec.clone_empty_in(StackN::<1, 256>);
tmp.push(any_vec.at(0).lazy_clone());
any_vec.push(tmp.pop().unwrap());
}
MemBuilder
接口,作为有状态的接口,允许创建可以与复杂自定义分配器一起工作的 Mem
。
no_std + no_alloc
这是一个 no_std
库,也可以在没有 alloc
的情况下工作。
变更日志
有关版本差异,请参阅 CHANGELOG.md。
已知替代方案
- type_erased_vec。允许以类型擦除的方式存储
Vec<T>
,但你需要执行操作时,需要先“转换”为具体类型。 - untyped_vec。一些操作(如
len
、capacity
)无需类型知识即可执行;但其余操作则需要具体类型。