2012-07-01 13 views
10

मैं इसstd :: istream_iterator के लिए प्रारंभ और अंत के मेरे ओवरलोड को खोजने के लिए क्यों नहीं है?

std::ifstream file(filename, std::ios_base::in); 
if(file.good()) 
{ 
    file.imbue(std::locale(std::locale(), new delimeter_tokens())); 
    for(auto& entry : std::istream_iterator<std::string>(file)) 
    { 
     std::cout << entry << std::endl;  
    } 
} 
file.close(); 

की तरह कोड जहां std::istream_iterator<std::string> के begin() और end() के रूप में परिभाषित कर रहे हैं

template<class T> 
std::istream_iterator<T> begin(std::istream_iterator<T>& stream) 
{ 
    return stream; 
} 

template<class T> 
std::istream_iterator<T> end(std::istream_iterator<T>& stream) 
{ 
    return std::istream_iterator<T>(); 
} 

जो क्या मार्क नेल्सन भी डॉ डॉब के here में के बारे में लिखा है इस प्रकार है। अफसोस, कोड त्रुटि संदेश

त्रुटि C3312 के साथ अपने दृश्य स्टूडियो 2012 को संकलित करने के लिए विफल रहता है: प्रकार के लिए कोई प्रतिदेय 'शुरू' समारोह 'std :: istream_iterator < _Ty>'

और

त्रुटि C3312: प्रकार के लिए कोई प्रतिदेय 'अंत' समारोह 'std :: istream_iterator < _Ty>'

प्रश्न: क्या ऐसा कुछ है जो मैंने नहीं देखा है, कंपाइलर में बग (संभावना नहीं है, लेकिन केवल मामले में) या ... अच्छा, कोई विचार?


Xeo द्वारा सलाह के अनुसार, यह प्रश्न काफी साफ हो गए हैं। अधिक पृष्ठभूमि और संदर्भ प्रदान करने के लिए यह स्टैक ओवरफ्लो पर मेरे other question से संबंधित है, मैं सोच रहा था कि सामान्य लूप की तुलना में लाइन आधारित पार्सिंग क्लीनर कैसे बनाना है। कोडिंग और इंटरनेट से जांच करने और उन्हें एक छोटा सा के रूप में

std::ifstream file(filename, std::ios_base::in); 
if(file.good()) 
{    
    file.imbue(std::locale(std::locale(), new delimeter_tokens())); 
    for(auto& entry : istream_range<std::string>(file) 
    { 
     std::cout << entry << std::endl;  
    } 
} 
file.close(); 

इस प्रकार है, लेकिन मामूली रोड़ा मैं उपाय करने की कोशिश की थी मैं एक काम कर स्केच था। मुझे लगता है कि कोड है कि संकलित करने के लिए और पसंद नहीं

for(auto& entry : istream_range<std::string>(file) 

कृपया, अलग इटरेटर लिख लेना चाहिए विफल रहता है के रूप में अधिक लिखने के लिए प्राकृतिक लगेगा। delimeter_tokensNawaz तरह परिभाषित किया गया है कृपया कोड संश्लेषण ब्लॉग here में के रूप में here (नहीं दोहराया कोड) और istream_range दिखाई है। मुझे लगता है कि उपरोक्त कोड संश्लेषण ब्लॉग पोस्ट

में अंतिम नियम (फ्री-स्टैंडिंग शुरू() और अंत() फ़ंक्शंस में फ़ॉलबैक) हमें मौजूदा कंटेनर को गैर-आक्रामक रूप से अनुकूलित करने की अनुमति देता है, जैसा कि प्रारंभ और अंत कार्यान्वयन कार्य करना चाहिए, लूप इंटरफ़ेस के लिए श्रेणी-आधारित पर।

इस प्रकार सभी प्रश्न (आईआर) प्रासंगिक पृष्ठभूमि के साथ मेरा प्रश्न।

+0

मैं स्वतंत्रता ले लिया वास्तविक प्रश्न पूछा प्रतिबिंबित करने के लिए सवाल शीर्षक बदलने के लिए। यदि आवश्यक हो तो वापस रोल करें या बदलें। – Xeo

+0

यह बेहतर है, मुझे लगता है। यह उन लोगों का ध्यान रखता है जो मेरे जैसे समाधान की तलाश में हैं और जिनके पास हल करने के लिए लुकअप समस्या है। मैं आपकी पोस्ट को उत्तर के रूप में कैसे बना सकता हूं (या कोई और इसे पूरा करता है)? – Veksi

+0

इसके लिए भी धन्यवाद! : डी – Veksi

उत्तर

7

रेंज-एडीएल पर निर्भर करता है यदि मूल सरणी (T foo[N]) के लिए विशेष हैंडलिंग और सदस्य begin/end कोई परिणाम नहीं देता है।

§6.5.4 [stmt.ranged] p1

  • अन्यथा, शुरू-expr और अंत exprbegin(__range) और end(__range) क्रमशः, जहां begin और end तर्क पर निर्भर देखने के साथ देखा जाता है (3.4.2)। इस नाम के प्रयोजनों के प्रयोजनों के लिए, नामस्थान std एक संबंधित नामस्थान है।

आपकी समस्या है, कि std::istream_iterator के जुड़े नाम स्थान (जाहिर है) है namespace std, नहीं ग्लोबल नेम स्पेस।

§3.4.2 [basic.lookup.argdep] p2

समारोह कॉल में शामिल प्रत्येक तर्क प्रकार T के लिए, वहाँ शून्य या अधिक संबद्ध नामस्थान का एक सेट और शून्य या अधिक संबद्ध वर्गों का एक सेट पर विचार किया जा रहा है। नामस्थानों और वर्गों के सेट पूरी तरह से फ़ंक्शन तर्कों के प्रकारों द्वारा निर्धारित किए जाते हैं [...]।

  • यदि T एक मौलिक प्रकार है, तो नामस्थानों और कक्षाओं के इसके संबंधित सेट दोनों खाली हैं।
  • यदि T एक वर्ग प्रकार (यूनियन समेत) है, तो इसके संबंधित वर्ग हैं: कक्षा स्वयं; जिस वर्ग की यह सदस्य है, यदि कोई है; और इसके प्रत्यक्ष और अप्रत्यक्ष आधार वर्ग। इसके संबंधित नामस्थान ऐसे नामस्थान हैं जिनके संबंधित वर्ग सदस्य हैं। इसके अलावा, यदि टी एक वर्ग टेम्पलेट विशेषज्ञता है, तो इसके संबंधित नामस्थान और कक्षाओं में भी शामिल हैं: टेम्पलेट प्रकार पैरामीटर के लिए प्रदान किए गए टेम्पलेट तर्कों के प्रकार से जुड़े नामस्थान और वर्ग [...]।

दूसरी बुलेट के अंतिम (उद्धृत) हिस्से को नोट करें। यह मूल रूप से इसका मतलब है कि एक वर्ग जो टेम्पलेट तर्क के रूप में ग्लोबल नेम स्पेस का एक सदस्य है का उपयोग कर बनाता कोड काम:

#include <iterator> 
#include <iostream> 

template<class T> 
std::istream_iterator<T> begin(std::istream_iterator<T> is){ 
    return is; 
} 
template<class T> 
std::istream_iterator<T> end(std::istream_iterator<T>){ 
    return std::istream_iterator<T>(); 
} 

struct foo{}; 

std::istream& operator>>(std::istream& is, foo){ 
    return is; 
} 

int main(){ 
    for(foo f : std::istream_iterator<foo>(std::cin)) 
    //        ^^^ 
    // make global namespace one of the associated namespaces 
    ; 
} 
+0

मैं अब आपका अनुसरण नहीं कर पा रहा हूं। अगर मुझे फ़ाइल स्ट्रीम से टोकननाइज्ड तार पढ़ना चाहिए तो वह नेमस्पेस एसोसिएशन कैसे काम करेगा? यही है, लूप में आप जिस फू को इंगित करते हैं वह मेरे मामले में तार होना चाहिए। – Veksi

+0

@ वेक्सी: असल में, मेरे उत्तर का केवल पहला भाग महत्वपूर्ण है: आप वैश्विक नामस्थान में 'std' सदस्यों के लिए श्रेणी के लिए अधिभार नहीं डाल सकते हैं। दूसरा भाग केवल एडीएल की एक quirkyness दिखाने के लिए था कि यह काम करने की अनुमति देगा। : पी – Xeo

+1

[इस क्यू एंड ए] पर टिप्पणी करते समय (http://stackoverflow.com/a/18321288/819272), मुझे [* मूल मुद्दा * 1442] के बारे में पता चला (http://wg21.cmeerw.net/cwg/ मुद्दा 1442) जो नियमों को थोड़ा सा बदलता है। नेमस्पेस 'std' अब एक संबंधित नेमस्पेस नहीं है और [* यह स्पष्ट रूप से उल्लेख किया गया है कि *] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3691.pdf)" शुरू करें और अंत में संबंधित नेमस्पेस (3.4.2) में देखा गया है। [नोट: साधारण अनक्वली फाई लुकअप (3.4.1) नहीं किया जाता है। - अंत नोट] " – TemplateRex

1

तर्क की वजह से तर्क देखने के लिए संकलक begin() और end()std नामस्थान में खोजने का प्रयास करता है। यदि आप वहां अपने कार्यों को डालते हैं, तो कोड संकलित करता है।

चूंकि नाम लुकअप सी ++ में एक जटिल समस्या है, इसलिए मैं पूरी तरह से सुनिश्चित नहीं हूं कि संकलक सही तरीके से व्यवहार कर रहा है या नहीं।

+1

आपको ओवरस्लोड को 'नेमस्पेस std' में रखने की अनुमति नहीं है। – Xeo

+0

लेकिन आप टेम्पलेट्स विशेषज्ञ कर सकते हैं, नहीं? – jrok

+2

@jrok: हाँ, लेकिन केवल आपके उपयोगकर्ता द्वारा परिभाषित प्रकारों के लिए, 'std' (आईआईआरसी) से उत्पन्न होने वाले प्रकारों के लिए नहीं। साथ ही, आप * आंशिक रूप से * फ़ंक्शन टेम्पलेट्स और फ़ंक्शन टेम्पलेट विशेषज्ञता को सामान्य रूप से विशेषज्ञ नहीं कर सकते हैं। – Xeo

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

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