2012-04-02 19 views
22

एप्लिकेशन विकसित करते समय, मुझे निम्न समस्या थी। मैं एक खाली std::list<string> वापस करना चाहता था जब दिया गया फ़ंक्शन पॉइंटर शून्य था, या अन्यथा उस फ़ंक्शन का परिणाम। यह मेरा कोड का एक सरलीकृत संस्करण है:प्रारंभिकizer_सूची से टर्नरी ऑपरेटर + सी ++ 11 कन्स्ट्रक्टर

typedef std::list<std::string> (*ParamGenerator)(); 

std::list<std::string> foo() { 
    /* ... */ 
    ParamGenerator generator = ...; 
    if(generator) 
     return generator(); 
    else 
     return {}; 
} 

हालांकि, मैं आमतौर पर इन मामलों में त्रिगुट (?:) ऑपरेटर का उपयोग करना चाहते, तो मैं इसे इस तरह का उपयोग कर की कोशिश की (हमेशा की तरह):

return generator ? generator() : {}; 

लेकिन यह त्रुटि आई:

somefile.cpp:143:46: error: expected primary-expression before ‘{’ token 
somefile.cpp:143:46: error: expected ‘;’ before ‘{’ token 

इसका मतलब मैं त्रिगुट ऑपरेटर का उपयोग नहीं कर सकता है एक initializer_list से उनके निर्माता का उपयोग कर बनाई वस्तुओं वापस जाने के लिए? क्या इसके लिए कोई विशेष कारण है?

+1

मेरी सलाह होगी: ** यह बिल्कुल मत करो **। इसे एक सामान्य एल्गोरिदम बनाएं जो एक इटरेटर (जिसका प्रकार टेम्पलेट पैरामीटर है) लेता है, इसलिए जब आप महसूस करते हैं कि 'std :: list' एक खराब विकल्प था, तो आप अपेक्षाकृत दर्द रहित तरीके से कुछ और बदल सकते हैं। –

+0

@ जेरीकॉफिन मैं शायद वह सलाह लेगा;)। मैं जानना चाहता हूं कि यह वैसे भी संभव है (या ऐसा क्यों नहीं है क्योंकि यह नहीं किया जा सकता है)। – mfontanini

+0

ठीक है, काफी उचित है। यह एक दिलचस्प सवाल है (जिसके लिए मैंने अप-वोट किया) भले ही मुझे लगता है कि सटीक एप्लिकेशन शायद सबसे अच्छा नहीं है। –

उत्तर

15

स्टैंडर्ड 8.5.4.1 में लिखते हैं: सूची-प्रारंभ उनमें से

Note: List-initialization can be used

  • as the initializer in a variable definition (8.5)
  • as the initializer in a new expression (5.3.4)
  • in a return statement (6.6.3)
  • as a function argument (5.2.2)
  • as a subscript (5.2.1)
  • as an argument to a constructor invocation (8.5, 5.2.3)
  • as an initializer for a non-static data member (9.2)
  • in a mem-initializer (12.6.2)
  • on the right-hand side of an assignment (5.17)

कुछ भी नहीं है एक त्रिगुट ऑपरेटर है। अधिक सरल return 1?{}:{}; भी अमान्य है, जो आप चाहते हैं वह असंभव है।

बेशक आप कन्स्ट्रक्टर std::list<std::string>{} को स्पष्ट रूप से कॉल कर सकते हैं, लेकिन मैं if - else -ब्लॉक को लिखने की अनुशंसा करता हूं जैसा कि आपने पहले ही किया है।

+0

ग्रेट, वह औचित्य था जिसे मैं ढूंढ रहा था। – mfontanini

3

जब आप {} करते हैं तो संकलक को आपके द्वारा अपेक्षित प्रकार के बारे में कोई जानकारी नहीं है, इसलिए यह केवल एक अर्थहीन अभिव्यक्ति है कि संकलक को पता नहीं है कि क्या करना है। : के दोनों पक्षों का मूल्यांकन अलग से किया जाता है, और तभी संकलक शिकायत करेगा यदि प्रकार मेल नहीं खाते हैं। मैं सिर्फ यह करना होगा:

return generator ? generator() : std::list<std::string>(); 
2

तुम सच में त्रिगुट ऑपरेटर की तरह, आप कुछ इस तरह की कोशिश कर सकते हैं:

return generator ? generator() : decltype(generator()) { "default value", "generator was empry" };

यह भले ही आप वापसी प्रकार बाद में बदल काम करेंगे।

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