2012-07-10 16 views
34

मुझे समझ में नहीं आता है कि ऑपरेटर के आरएचएस पर प्रारंभकर्ता सूचियों का उपयोग क्यों नहीं किया जा सकता है। पर विचार करें:ऑपरेटरों की प्रारंभिक सूचियां और आरएचएस

class foo { }; 

struct bar 
{ 
    template<typename... T> 
    bar(T const&...) { } 
}; 

foo& operator<<(foo& f, bar const&) { return f; } 

int main() 
{ 
    foo baz; 
    baz << {1, -2, "foo", 4, 5}; 

    return 0; 
} 

नवीनतम बजना (जीसीसी के साथ-साथ) की शिकायत है:

clang.cc:14:9: error: initializer list cannot be used on the right hand side of operator '<<' 
    baz << {1, -2, "foo", 4, 5}; 
    ^~~~~~~~~~~~~~~~~~~~~ 

    ^~~~~~~~~~~~~~~~ 

क्यों सी ++ मानक इस ना करे होगा? या अलग-अलग रखें, यह

baz << bar{1, -2, "foo", 4, 5}; 

के विरोध में विफल क्यों होता है?

+9

क्योंकि आपने आरएचएस पर 'प्रारंभकर्ता_सूची <>' लेने के लिए 'ऑपरेटर <<' अधिभारित नहीं किया है ... आपका वास्तविक प्रश्न क्या है? – ildjarn

+0

मैं उम्मीद कर रहा था कि यह 'baz << bar {1, 2, 3, 4, 5} के बराबर है; ', लेकिन ऐसा लगता है कि कोई रूपांतरण नहीं होता है। – mavam

+3

यदि यह वही व्यवहार है जो आप चाहते हैं, तो आपको 'बार' को एक गैर-स्पष्ट कन्स्ट्रक्टर देने का प्रयास करना चाहिए जो एक 'प्रारंभकर्ता_सूची <> 'लेता है। – ildjarn

उत्तर

45

वास्तव में सी ++ 11 का अंतिम संस्करण द्विआधारी ऑपरेटर के दाएं हाथ की ओर (या उस मामले के लिए बाएं हाथ की ओर) प्रारंभिक सूचियों के उपयोग को सक्षम नहीं करता है।

सबसे पहले, प्रारंभकर्ता-सूचियां मानक के §5 में परिभाषित नहीं हैं। कार्यों के तर्क, साथ ही द्विआधारी ऑपरेटरों के तर्कों को आम तौर पर अभिव्यक्ति होना चाहिए, और §5 में परिभाषित अभिव्यक्तियों के व्याकरण में ब्रेस-इनिट-सूचियों (यानी शुद्ध प्रारंभकर्ता-सूचियों के लिए वाक्यविन्यास शामिल नहीं है; ध्यान दें कि एक टाइपनाम के बाद bar {2,5,"hello",7} एक ब्रेस-इनिट-सूची है, हालांकि एक अभिव्यक्ति है)।

§8.5.4/1:

क्रम सुविधाजनक स्थान पर शुद्ध प्रारंभकर्ता-सूचियों का उपयोग करने में सक्षम होने के लिए, मानक विभिन्न अपवाद है, जो निम्नलिखित (गैर मानक) टिप्पणी में संक्षेप में परिभाषित करता है [...] नोट: सूची-प्रारंभ किया जा सकता है
- एक नया अभिव्यक्ति (5.3.4)
में प्रारंभकर्ता के रूप में - - एक चर परिभाषा (8.5)
में प्रारंभकर्ता के रूप में एक वापसी बयान में (6.6.3)
- एक समारोह के रूप में तर्क टी (5.2.2)
- एक निर्माता मंगलाचरण (8.5, 5.2.3)
लिए एक तर्क के रूप - - एक सबस्क्रिप्ट (5.2.1)
के रूप में एक गैर स्थैतिक डेटा सदस्य के लिए एक प्रारंभकर्ता के रूप में (9.2)
- एक सदस्य-प्रारंभकर्ता (12.6.2)
में - एक काम के दाएँ हाथ की ओर पर (5.17)
[...]

स्पष्ट रूप से ऊपर चौथे आइटम शुद्ध initializer- की अनुमति देता है फंक्शन तर्क के रूप में सूचियां (यही कारण है कि operator<<(baz, {1, -2, "foo", 4, 5}); काम करता है), पांचवां व्यक्ति इसे सबस्क्रिप्ट अभिव्यक्तियों में अनुमति देता है (यानी operator[] के तर्क के रूप में, उदा। mymap[{2,5,"hello"}] कानूनी है), और अंतिम आइटम उन्हें असाइनमेंट (लेकिन सामान्य बाइनरी ऑपरेटरों नहीं) के दाईं ओर की अनुमति देता है।

वहाँ है द्विआधारी ऑपरेटरों+, * या << की तरह है, इसलिए यदि आप एक शुद्ध प्रारंभकर्ता सूची (अर्थात ऐसा typename साथ पहले नहीं है) उनमें से दोनों तरफ नहीं डाल सकते के लिए इस तरह के कोई अपवाद नहीं।

इस के लिए कारणों के रूप में, 2007 से Stroustrup और डॉस रीस द्वारा एक draft/discussion paper N2215 विभिन्न संदर्भों में प्रारंभकर्ता-सूची के साथ कई मुद्दों में अंतर्दृष्टि का एक बहुत प्रदान करता है।विशेष रूप से, बाइनरी ऑपरेटरों (सेक्शन 6.2) पर एक अनुभाग है:

प्रारंभकर्ता सूचियों के अधिक सामान्य उपयोगों पर विचार करें। उदाहरण के लिए:

v = v+{3,4}; 
v = {6,7}+v; 

जब हम कार्यों के लिए वाक्यात्मक चीनी के रूप में ऑपरेटरों पर विचार, हम स्वाभाविक रूप से

v = operator+(v,{3,4}); 
v = operator+({6,7},v); 

यह भाव को प्रारंभकर्ता सूचियों के उपयोग का विस्तार करने के इसलिए स्वाभाविक है करने के लिए ऊपर बराबर पर विचार करें। ऐसे कई उपयोग हैं जहां ऑपरेटरों के साथ संयुक्त प्रारंभिक सूचियां एक "प्राकृतिक" संकेत है।
हालांकि, एलआर (1) व्याकरण लिखना तुच्छ नहीं है जो प्रारंभिक सूचियों के मनमाने ढंग से उपयोग की अनुमति देता है। एक ब्लॉक भी {के साथ शुरू होता है, इसलिए एक प्रारंभकर्ता सूची को अभिव्यक्ति की पहली (बाएं) इकाई के रूप में अनुमति देने से व्याकरण में अराजकता हो सकती है।
सबस्क्रिप्ट्स, और व्याकरण के समान पृथक हिस्सों में प्रारंभिक सूचियों को बाइनरी ऑपरेटरों के दाएं हाथ के संचालन के रूप में अनुमति देने के लिए तुच्छ है। असली समस्या ;a={1,2}+b; को असाइनमेंट-स्टेटमेंट के रूप में ;{1,2}+b; की अनुमति के बिना अनुमति देने के लिए है। हमें संदेह है कि प्रारंभकर्ता की इजाजत दी सूचीबद्ध करता है के रूप में दाएँ हाथ है, लेकिन न ही [वैसा] के रूप में सबसे ऑपरेटरों के लिए बाईं ओर के तर्क, एक kludge की बहुत अधिक है [...]

दूसरे शब्दों में, प्रारंभकर्ता-सूचियों में दाईं तरफ पर सक्षम नहीं हैं क्योंकि वे बाएं हाथ की ओर पर सक्षम नहीं हैं, और वे बाईं तरफ सक्षम नहीं हैं क्योंकि इससे पार्सर्स के लिए बहुत बड़ी चुनौती हो सकती है।

मुझे आश्चर्य है कि समस्या प्रारंभकर्ता-सूची वाक्यविन्यास के लिए घुंघराले ब्रेसिज़ के बजाय एक अलग प्रतीक चुनकर सरलीकृत हो सकती है।

+2

एक अलग प्रतीक ने अधिक चीजों को संभव बना दिया हो सकता है, लेकिन '{}' सरणी प्रारंभकर्ताओं और सीओ 8 से प्राप्त पीओडी संरचना प्रारंभकर्ताओं का ऐसा प्राकृतिक विस्तार है। – aschepler

+1

इस स्पष्टीकरण के लिए धन्यवाद - मैंने किरायेदार ऑपरेटर की सच्चाई की खोज की? {1,2,3}: {4,5,6} '- इसलिए यह केवल बाइनरी ऑपरेटरों की समस्या नहीं है ... – PiotrNycz

+1

@PiotrNycz यह एक नहीं हो सकता है पार्सिंग मुद्दा, लेकिन एक प्रकार की कटौती मुद्दा। टर्नरी ऑपरेटर के दोनों विकल्पों को एक सामान्य प्रकार से सहमत होना चाहिए, और कुछ भी परिणाम मूल्य श्रेणी निर्धारित करना होगा। ब्रेसिज़ कार्यक्रम के अर्थ को अस्पष्ट करते हैं। यह '?' में बेहतर है और '{' से पहले टाइप-नाम डाला गया है, और यह किसी भी अभिव्यक्तित्मक शक्ति का त्याग नहीं करता है। – Potatoswatter

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