2016-08-13 25 views
11

क्या मैं ब्रेस-संलग्न प्रारंभकर्ता के बजाय std::initializer_list ऑब्जेक्ट का उपयोग करके सरणी प्रारंभ कर सकता हूं?क्या मैं ब्रेस-संलग्न प्रारंभकर्ता के बजाय std :: startizer_list का उपयोग करके एक सरणी प्रारंभ कर सकता हूं?

में जाना जाता है के रूप में, हम यह कर सकते हैं: http://en.cppreference.com/w/cpp/language/aggregate_initialization

unsigned char b[5]{"abc"}; 
// equivalent to unsigned char b[5] = {'a', 'b', 'c', '\0', '\0'}; 

int ar[] = {1,2,3}; 
std::array<int, 3> std_ar2{ {1,2,3} }; // std::array is an aggregate 
std::array<int, 3> std_ar1 = {1, 2, 3}; 

लेकिन मैं std::initializer_list il; द्वारा एक सरणी प्रारंभ नहीं कर सकते हैं:

http://ideone.com/f6aflX

#include <iostream> 
#include <initializer_list> 
#include <array> 

int main() { 

    int arr1[] = { 1, 2, 3 }; // OK 
    std::array<int, 3> arr2 = { 1, 2, 3 }; // OK 

    std::initializer_list<int> il = { 1, 2, 3 }; 
    constexpr std::initializer_list<int> il_constexpr = { 1, 2, 3 }; 

    //int arr3[] = il; // error 
    //int arr4[] = il_constexpr; // error 

    //std::array<int, 3> arr5 = il; // error 
    //std::array<int, 3> arr6 = il_constexpr; // error 

    return 0; 
} 

लेकिन यह कैसे मैं करने के लिए उपयोग कर सकते हैं std::initializer_list il; एक सरणी शुरू करें?

+5

दोबारा शुरू किया गया .. "डुप्ड" एक सदस्य सरणी के प्रारंभिककरण के बारे में एक सामान्य प्रश्न था {{}} '। यह 'std :: startizer_lists' का उपयोग करके 'std ::' प्रकार (इसमें कोई बदलाव नहीं है!) प्रारंभ करने के लिए कहता है। वे बहुत अलग प्रश्न हैं। –

+0

@Alex क्या आप 'एल्गोरिदम '([उदाहरण] (https://godbolt.org/g/cKiBNg) से' प्रतिलिपि 'का उपयोग नहीं कर सकते हैं? – skypjack

उत्तर

8

अन्य ने उत्तर दिया सही ढंग से कहा गया कि यह संभव नहीं है। लेकिन छोटे सहायकों के साथ, आप बहुत करीब प्राप्त कर सकते हैं

template<typename T, std::size_T N, std::size_t ...Ns> 
std::array<T, N> make_array_impl(
    std::initializer_list<T> t, 
    std::index_sequence<Ns...>) 
{ 
    return std::array<T, N>{ *(t.begin() + Ns) ... }; 
} 

template<typename T, std::size_t N> 
std::array<T, N> make_array(std::initializer_list<T> t) { 
    if(N > t.size()) 
     throw std::out_of_range("that's crazy!"); 
    return make_array_impl<T, N>(t, std::make_index_sequence<N>()); 
} 

आप और अधिक काम arounds के लिए खुले हैं, तो आप एक वर्ग में डाल मामलों में आप किसी braced init सूची पारित के लिए स्थिर प्रसिद्ध लंबाई उल्लंघन को पकड़ने के लिए कर सकते हैं ।लेकिन चेतावनी दी है कि ज्यादातर लोग हैं जो इस कोड को पढ़ने के सिर डेस्क जाएगा

template<typename T, std::size_t N> 
struct ArrayInitializer { 
    template<typename U> struct id { using type = U; }; 
    std::array<T, N> t; 

    template<typename U = std::initializer_list<T>> 
    ArrayInitializer(typename id<U>::type z) 
     :ArrayInitializer(z, std::make_index_sequence<N>()) 
    { 
     if(N > z.size()) 
      throw std::out_of_range("that's crazy!"); 
    } 

    template<typename ...U> 
    ArrayInitializer(U &&... u) 
     :t{ std::forward<U>(u)... } 
    { } 

private: 
    template<std::size_t ...Ns> 
    ArrayInitializer(std::initializer_list<T>& t, 
        std::index_sequence<Ns...>) 
     :t{ *(t.begin() + Ns) ... } 
    { } 
}; 

template<typename T, std::size_t N> 
std::array<T, N> f(ArrayInitializer<T, N> ai) { 
    return std::move(ai.t); 
} 

int main() { 
    f<int, 5>({1, 2, 3, 4, 5}); // OK 
    f<int, 5>({1, 2, 3, 4, 5, 6}); // "too many initializers for array<int, 5>" 

    std::initializer_list<int> il{1, 2, 3, 4, 5}; 
    f<int, 5>(il); // ok 
} 

ध्यान दें कि दोनों जवाब और "सिर डेस्क" मामले के शीर्ष पर गैर स्थिर मामले केवल जाँच करते हैं कि क्या आप भी प्रदान करते हैं कुछ शुरुआती तत्व, और initializer_list मामले के लिए त्रुटियां। यदि आप initializer_list मामले के लिए बहुत अधिक प्रदान करते हैं, तो पीछे के तत्वों को केवल अनदेखा किया जाता है।

+0

टेक्स्ट को ठीक किया गया धन्यवाद! हां, दोनों उदाहरण प्रयोग योग्य हैं: http://ideone.com/s0ciUW और http://ideone.com/fbnM6W – Alex

6

जहाँ तक मुझे पता है, नहीं: आप std::initializer_list के साथ std::array प्रारंभ नहीं कर सकते हैं।

समस्या यह है कि std::array क्लासिक सी-शैली सरणी के लिए हल्के प्रतिस्थापन (एक रैपर) के रूप में लक्षित है। तो प्रकाश जो रचनाकारों के बिना है, इसलिए केवल अंतर्निहित कन्स्ट्रक्टर का उपयोग किया जा सकता है।

समग्र प्रारंभिक (अंतर्निहित कन्स्ट्रक्टर के माध्यम से) के साथ निर्माण संभव है क्योंकि यह सी-शैली सरणी के लिए संभव है।

लेकिन std::initializer_list एक वर्ग है, जो कुल मिलाकर इनइजियलाइजेशन से अधिक जटिल है।

आप उदाहरण के द्वारा, को प्रारंभ कर सकते हैं, एक एक std::initializer_list साथ std::vector लेकिन केवल क्योंकि वहाँ कोई स्पष्ट निर्माता, std::vector के लिए, कि एक std::initializer_list प्राप्त करते हैं। लेकिन std::vector एक भारी वर्ग है।

एकमात्र समाधान जो मैं देखता हूं वह एक 2 कदम तरीका है: (1) निर्माण और (2) std::initializer_list मूल्यों की प्रति।

std::array<int, 3> arr5; 

auto ui = 0U; 
auto cit = il.cbegin(); 

while ((ui < arr5.size()) && (cit != il.cend())) 
    arr5[ui++] = *cit++; 

p.s .: मेरी खराब अंग्रेजी के लिए खेद है।

+6

_Bad अंग्रेजी? _ आप मेरे अधिकांश सहयोगियों से बेहतर लिखते हैं। आपको स्टैक ओवरफ़्लो उत्तरों या प्रश्नों में ऐसी टिप्पणियों की आवश्यकता नहीं है। समुदाय कुछ भी संपादित करेगा जो समझ में नहीं आता है। –

+1

@ एंडोनएम। कोलेमैन - धन्यवाद; मैं अपनी भाषा असुरक्षा को अनदेखा करने की कोशिश करूंगा। – max66

2

std::array के साथ समस्या यह है कि यह कुल प्रकार होना आवश्यक है, इसलिए इसमें रचनाकार नहीं हैं।

इसलिए केवल प्रारंभिक प्रारंभिक या छोटी प्रतिलिपि संभव है। std::initializer_liststd::array के अलावा एक वर्ग है, इसलिए एक (गायब) निहित रूपांतरण की आवश्यकता है।

http://en.cppreference.com/w/cpp/language/aggregate_initialization और http://en.cppreference.com/w/cpp/container/array संदर्भ के लिए देखें।

+0

[पीओडी की कौन सी विशिष्ट आवश्यकता इस पर प्रतिबंध लगाती है?] (Http://coliru.stacked-crooked.com/a/d332ff1ce89c8817) – chris

+0

@ क्रिस: क्षमा करें, नहीं * पीओडी *, लेकिन * कुल * प्रकार। देखें http://en.cppreference.com/w/cpp/language/aggregate_initialization और http://en.cppreference.com/w/cpp/container/array। बस –

संबंधित मुद्दे