मैं निरंतर जेनरिक का उपयोग करके स्ट्रिंग्स का एक निश्चित आकार का सरणी कैसे बना सकता हूं?
मेरे पास एक सामान्य जेनेरिक का उपयोग करने वाला एक फ़ंक्शन है:
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
।
जवाब
आप इसके साथ कर सकते हैं 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
। एक बार ऊपर कास्ट जेनरिक स्थिर हो गया है)।
किस मामले में अब आपके पास होगा:
fn foo<const S: usize>() -> Vec<[String; S]> {
// Some code
let mut row: [String; S] = DefaultArray::default_array();
// Some code
todo!()
}
इसे खेल के मैदान पर देखें ।