2013-07-22 32 views
29

मान लीजिए कि आप एक ऐसा फ़ंक्शन लिख रहे हैं जो std::initializer_list को list कहलाता है, और फ़ंक्शन को list के तत्वों को यादृच्छिक पहुंच की आवश्यकता होती है। list.begin()[i] के बजाय list[i] लिखना सुविधाजनक होगा। तो std::initializer_listoperator[] की परिभाषा क्यों प्रदान नहीं करता है?`std :: startizer_list` क्यों एक सबस्क्रिप्ट ऑपरेटर प्रदान नहीं करता है?

मैं किसी भी मामले के बारे में नहीं सोच सकता जहां operator[]const T& लौटने पर अच्छी तरह से परिभाषित नहीं किया जाएगा। दक्षता यहां समस्या नहीं प्रतीत होती है, क्योंकि std::initializer_list<T>::iterator को const T* पर अलिया किया गया है, जो स्पष्ट रूप से एक यादृच्छिक-पहुंच इटरेटर है।

+1

मुझे लगता है क्योंकि इसका मुख्य उपयोग-मामला अनुक्रमिक रूप से संसाधित होने वाली सूची है। – PlasmaHH

+2

एक सामान्य उपयोग केस एक निर्माता के लिए है जो स्मृति के ब्लॉक को आवंटित करता है और 'allocator.construct (p, v) 'का उपयोग करके ब्लॉक में तत्वों को बनाता है।हालांकि सूची को अनुक्रमिक रूप से संसाधित किया गया है, बाहरी फॉर-लूप में पहले से ही एक काउंटर है जो स्वयं को 'ऑपरेटर []' वाक्यविन्यास में उधार देता है। –

+0

@ शून्य-सूचक क्या आप सामान्य रूप से इन परिस्थितियों में * कॉपी * नहीं करेंगे? इस तरह आपको लूप की आवश्यकता नहीं है, और मैं आम तौर पर एक स्पष्ट लूप से बचता हूं। हालांकि सवाल अभी भी वैध है। –

उत्तर

9

सी ++ प्रोग्रामिंग भाषा की धारा 17.3.4.2 (पी 497।) में Bjarne Stroustrup, 4 संस्करण के अनुसार:

दुर्भाग्य से, initializer_list subscripting प्रदान नहीं करता है।

कोई और कारण नहीं दिया गया है। एक चूक

  1. यह है, या
  2. क्योंकि initializer_list वर्ग एक सरणी के साथ लागू किया जाता है और आप सीमा सुरक्षित पहुँच प्रदान करने की जाँच कर दिया था:

    मेरा अनुमान है कि यह इन कारणों में से एक है है , यह और अधिक आसानी से unsafely इस्तेमाल किया जा सकता है, तो यह है कि इंटरफेस प्रदान की गई थी, या

  3. एसटीडी एल्गोरिदम यात्रा प्रतिमान के अनुरूप होना करने के लिए, या
  4. क्योंकि initializer_lists रहे हैं, उनके स्वभाव से, तदर्थ, वहाँ से त्रुटि के लिए कक्ष खाली नहीं हैं उन्हें सीधे संबोधित

2 और 4 ध्वनि प्रकार कमजोर। जैसा कि 3. मेरा पैसा 1.

+1

बस आज बजेर्न की किताब पढ़ें, और कारणों की तलाश में था ... – lpapp

2

यह वास्तव में थोड़ा परेशान है, एसडी :: प्रारंभकर्ता_सूची के लिए स्क्वायर ब्रैकेट ऑपरेटर नहीं है, क्योंकि एक विशिष्ट अनुक्रमणिका के लिए यादृच्छिक प्रत्यक्ष पहुंच की आवश्यकता एक उचित परिदृश्य है।

हालांकि, इस क्षमता कुछ सरल कोड के साथ जोड़ा जा सकता है:,

// the class _init_list_with_square_brackets provides [] for initializer_list 
template<class T> 
struct _init_list_with_square_brackets { 
    const std::initializer_list<T>& list; 
    _init_list_with_square_brackets(const std::initializer_list<T>& _list): list(_list) {} 
    T operator[](unsigned int index) { 
     return *(list.begin() + index); 
    } 
}; 

// a function, with the short name _ (underscore) for creating 
// the _init_list_with_square_brackets out of a "regular" std::initializer_list 
template<class T> 
_init_list_with_square_brackets<T> _(const std::initializer_list<T>& list) { 
    return _init_list_with_square_brackets<T>(list); 
} 

अब हम एक नया वैश्विक समारोह _ (अंडरस्कोर) नाम दिया है जो शायद विधि ++ एक वैश्विक सी के लिए एक अच्छा नाम नहीं है जब तक कि हम सी ++ के लिए कुछ "अंडरस्कोर-जैसी" उपयोगिता lib बनाना चाहते हैं, जिसमें इसका अपना नामस्थान होगा, अन्य सभी उपयोगी उपयोगों के लिए _ फ़ंक्शन को ओवरलोड करना होगा।

नई _ समारोह इस तरह अब इस्तेमाल किया जा सकता:

void f(std::initializer_list<int> list) { 
    cout << _(list)[2]; // subscript-like syntax for std::initializer_list! 
} 

int main() { 
    f({1,2,3}); // prints: 3 
    cout << _({1,2,3})[2]; // works also, prints: 3 
    return 0; 
} 

उल्लेखनीय यह है कि ऊपर दी गई समाधान प्रदर्शन के मामले में एक अच्छा सौदा अगर आप एसटीडी की कई मदों अधिक समय तक नहीं है: : _init_list_with_square_brackets से ऊपर दिए गए सुझाए गए प्रकार की एक अस्थायी वस्तु के रूप में प्रारंभकर्ता_सूची बार-बार बनाई जाती है। जो फिर से आश्चर्य उठाता है कि यह मानक द्वारा क्यों प्रदान नहीं किया गया था।

+0

यह अच्छा है। प्रश्न पर @ यक्क की टिप्पणी को अपहरण करने का एक विकल्प, "ऑटो mylist = list.begin()" और फिर मेरी सूची [n] काम करता है। –

+4

यदि मुझे कोड में सिंटैक्स दिखाई देगा तो मैं तुरंत "wtf" होगा। मैं अनजान हूं कि '_' वास्तव में एक आईडी है, जो कम से कम एक समारोह को दर्शाता है। रैली की तरह, "wtf"। मैंने शायद इसे अंततः समझ लिया होगा ('_' ?? नामक आईडी के लिए" परिभाषा पर जाएं "काम करता है), लेकिन यह कोडर के परिवार के मेरे तीव्र, तेज़ और दोहराए गए उल्लेखों को कम करने के लिए कुछ भी नहीं करेगा उस। मेरी सलाह सिर्फ 'list.begin() [i] 'के साथ जाती है। मुझे डाउनवोट करने के लिए खेद है क्योंकि यह एक अच्छी चाल है, भाषा के अनुसार, लेकिन व्यवहार में यह पीछे हट जाएगा। – bolov

+0

मुझे लगता है कि आप वास्तव में एक प्रति के बजाय 'विपक्ष टी' 'वापस करना चाहते हैं। – MikeMB

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