상수 제네릭을 사용하여 고정 크기의 문자열 배열을 어떻게 만들 수 있습니까?
상수 제네릭을 사용하는 함수가 있습니다.
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
}
String
내 경우에 고정 크기 배열을 어떻게 만들 수 있습니까? 특성을 구현하지 않기 let mut row: [String; S] = ["".to_string(), S];
때문에 작동 String
하지 않습니다 Copy
.
답변
4 eggyal
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!()
}
물론 이러한 논리를 자신의 특성으로 추상화하는 것이 더 쉬울 수 있습니다.
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()
}
}
}
(보다는 자신의 특성을 사용하는 유일한 이유는 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!()
}
놀이터 에서 확인하세요 .