मैं निरंतर जेनरिक का उपयोग करके स्ट्रिंग्स का एक निश्चित आकार का सरणी कैसे बना सकता हूं?

Aug 17 2020

मेरे पास एक सामान्य जेनेरिक का उपयोग करने वाला एक फ़ंक्शन है:

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 Aug 17 2020 at 23:49

आप इसके साथ कर सकते हैं 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!()
}

इसे खेल के मैदान पर देखें ।