2010-09-12 14 views
12

इस कोड काम करता है:समारोह बनाम सी में चर घोषणा ++

std::ifstream f(mapFilename.c_str()); 
std::string s = std::string(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()); 
ParseGameState(s); 

जिससे mapFilename एक std::string और void ParseGameState(const std::string&); है।

और यह नहीं करता है:

game.cpp: In member function ‘int Game::LoadMapFromFile(const std::string&)’: 
game.cpp:423: error: no matching function for call to ‘ParseGameState(std::string (&)(std::istreambuf_iterator<char, std::char_traits<char> >, std::istreambuf_iterator<char, std::char_traits<char> > (*)()))’ 
game.cpp:363: note: candidates are: ParseGameState(const std::string&) 

तो ऐसा लगता है कि यह पहचानता एक समारोह घोषणा के रूप में s और नहीं इस मामले में एक चर घोषणा:

std::ifstream f(mapFilename.c_str()); 
std::string s(std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()); 
ParseGameState(s); 

यह त्रुटि है।

वह क्यों है? क्या यह जीसीसी 4.2.1 (ऐप्पल बिल्ड) में एक बग है? या जीसीसी इसे सही तरीके से संभालती है? क्या यह सी ++ मानक में अपरिभाषित है?

उत्तर

14

यह सी ++ का "सबसे परेशान पार्स है।" इसके लिए एक त्वरित Google को बहुत सारे विवरणों के साथ बहुत सारी हिट चालू करनी चाहिए। मूल जवाब यह है कि हां, कंपाइलर एक फ़ंक्शन घोषणा के रूप में इसका इलाज कर रहा है - और सी ++ की आवश्यकता है कि ऐसा करें। आपके कंपाइलर के साथ कुछ भी गलत नहीं है (कम से कम इस संबंध में)।

यदि यह कोई सुविधा है, तो इसमें भाग लेने में आपके पास बहुत अच्छी कंपनी है। वास्तव में, यह पर्याप्त रूप से आम है कि C++ 0x को एक बड़े ब्रेस-प्रारंभकर्ता सिंटैक्स को बड़े हिस्से में जोड़ा जाता है क्योंकि यह इस अस्पष्टता से बचाता है।

std::string s{std::istreambuf_iterator<char>(f), std::istreambuf_iterator<char>()}; 

कर देगा कि यह स्पष्ट ब्रेसिज़ की सामग्री s नाम के एक समारोह के लिए मापदंडों के s, प्रकार नहीं आरंभ के लिए मान करने का इरादा कर रहे हैं कि: यह उपयोग कर, आप की तरह कुछ लिख सकते हैं। मुझे नहीं पता कि ऐप्पल के पास अभी तक इसका बंदरगाह है, लेकिन जीसीसी ने संस्करण 4.5 (या तो) के रूप में नया वाक्यविन्यास स्वीकार किया है।

संपादित करें: N3092 रीडिंग, जोहान्स (सामान्य रूप में) काफी सही है। लागू भाषा (§8.5.4/3/5) है: "यदि टी में प्रारंभकर्ता-सूची निर्माता है, तो तर्क सूची में प्रारंभिक सूची को एक तर्क के रूप में शामिल किया जाता है, अन्यथा, तर्क सूची में प्रारंभकर्ता के तत्व होते हैं सूची।"

तो, के बाद से std::string एक प्रारंभकर्ता-सूची निर्माता है, यह करने के लिए "सामान" दो istreambuf_iterator एक प्रारंभकर्ता सूची में प्रयास होता है, और std::string ctor कि एक प्रारंभकर्ता सूची लेता है कि पास - लेकिन यह है कि हो सकता है एक मिस्चैच टाइप करें, इसलिए कोड संकलित नहीं हो सकता है। किसी अन्य प्रकार के प्रकार के लिए (std::string के विपरीत में प्रारंभकर्ता-सूची सीटीओआर नहीं है) उपरोक्त परिवर्तन कार्य करेगा (उपरोक्त उद्धरण में "अन्यथा ..." के लिए धन्यवाद)। std::string के मामले में, आपको वर्तमान विकल्पों में से एक का उपयोग करना होगा जैसे std::string s = std:string(...)

मैं गलत सुझाए गए फिक्स के लिए क्षमा चाहता हूं - इस मामले में, यह सब खराब है क्योंकि यह किसी ऐसे मुद्दे को भ्रमित करता है जो शायद अपने आप पर अत्यधिक भ्रमित हो जाएगा, और यदि कुछ भी सावधानीपूर्वक स्पष्टीकरण की आवश्यकता होगी, खासकर अगले कुछ वर्षों में वर्षों।

+1

धन्यवाद! [यहां डब्ल्यूपी पर] (http://en.wikipedia.org/wiki/Most_vexing_parse) सबसे अधिक परेशान पार्स के बारे में भी एक अच्छी व्याख्या है। – Albert

+1

ऐसा लगता है कि उपर्युक्त 'std :: string' परिवर्तनीय घोषणा C++ 0x में काम नहीं करेगी: क्योंकि 'std :: string' में प्रारंभकर्ता सूची निर्माता है, संपूर्ण' {...} 'को एक ही तर्क के रूप में लिया जाएगा, और' startizer_list 'पैरामीटर को प्रारंभ करने का प्रयास करेगा और संकलित करने में विफल :( –

+1

@ जोहान्स: हाँ, मुझे लगता है कि आप सही हैं। मुझे आश्चर्य है कि यह बेहतर नहीं होगा यदि इसे एक सूची-प्रारंभकर्ता पर विचार करने के बजाय और फिर (केवल अगर वह मौजूद नहीं था) पर विचार करने के बजाय अन्य सीटीर्स पर विचार करें, अगर इसके बजाय यह सिर्फ एक अधिभार सेट बनाया गया है और एक अच्छा मैच चुना है - शायद मामूली समायोजन के साथ जो एक startizer_list मिलान की भलाई के संबंध में कोई रूपांतरण के बराबर नहीं होगा (इस सिद्ध के साथ कि मैंने केवल कुछ मिनटों के बारे में सोचा है, जिससे मुझे एक सूक्ष्म (या यहां तक ​​कि चमकदार) समस्या हो सकती है जो मुझे याद आ रही है) –

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