我有一个使用常量泛型的函数:
fn foo<const S: usize>() -> Vec<[String; S]> {
// Some code
let mut row: [String; S] = Default::default(); //It sucks because of default arrays are specified up to 32 only
// Some code
}
Run Code Online (Sandbox Code Playgroud)
在我的情况下,如何创建固定大小的Strings 数组?let mut row: [String; S] = ["".to_string(), S];不起作用,因为String没有实现该Copy特征。
您可以使用MaybeUninit和 来做到这一点unsafe:
use std::mem::MaybeUninit;
fn foo<const S: usize>() -> Vec<[String; S]> {
// Some code
let mut row: [String; S] = unsafe {
let mut result = MaybeUninit::uninit();
let start = result.as_mut_ptr() as *mut String;
for pos in 0 .. S {
// SAFETY: safe because loop ensures `start.add(pos)`
// is always on an array element, of type String
start.add(pos).write(String::new());
}
// SAFETY: safe because loop ensures entire array
// has been manually initialised
result.assume_init()
};
// Some code
todo!()
}
Run Code Online (Sandbox Code Playgroud)
当然,将这样的逻辑抽象为你自己的特质可能会更容易:
use std::mem::MaybeUninit;
trait DefaultArray {
fn default_array() -> Self;
}
impl<T: Default, const S: usize> DefaultArray for [T; S] {
fn default_array() -> Self {
let mut result = MaybeUninit::uninit();
let start = result.as_mut_ptr() as *mut T;
unsafe {
for pos in 0 .. S {
// SAFETY: safe because loop ensures `start.add(pos)`
// is always on an array element, of type T
start.add(pos).write(T::default());
}
// SAFETY: safe because loop ensures entire array
// has been manually initialised
result.assume_init()
}
}
}
Run Code Online (Sandbox Code Playgroud)
(使用您自己的特征的唯一原因是Default后者的实现会与标准库中提供的最多 32 个元素的数组相冲突;我完全希望标准库将其实现替换Default为类似于一旦 const 泛型稳定下来)。
在这种情况下,您现在将拥有:
fn foo<const S: usize>() -> Vec<[String; S]> {
// Some code
let mut row: [String; S] = DefaultArray::default_array();
// Some code
todo!()
}
Run Code Online (Sandbox Code Playgroud)
在操场上看到它。
| 归档时间: |
|
| 查看次数: |
1139 次 |
| 最近记录: |