2013-06-03 6 views
14

उपयोग नहीं कर सकते निम्नलिखित कोड ठीक संकलित:समारोह नाम दूरी

#include <string> 

int dist(std::string& a, std::string& b) { 
    return 0; 
} 

int main() { 
    std::string a, b; 
    dist(a, b); 
    return 0; 
} 

लेकिन जब मैं जिले से दूरी के समारोह का नाम बदलने:

#include <string> 

int distance(std::string& a, std::string& b) { 
    return 0; 
} 

int main() { 
    std::string a, b; 
    distance(a, b); 
    return 0; 
} 

मैं इस त्रुटि मिलती है जब (जीसीसी 4.2 संकलन .1):

/usr/include/c++/4.2.1/bits/stl_iterator_base_types.h: In instantiation of ‘std::iterator_traits<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >’: 
b.cpp:9: instantiated from here 
/usr/include/c++/4.2.1/bits/stl_iterator_base_types.h:129: error: no type named ‘iterator_category’ in ‘struct std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ 

मैं फ़ंक्शन दूरी का नाम क्यों नहीं दे सकता?

+0

मुझे पता था कि समस्या क्या थी। अगर मैं केवल 3 घंटे पहले यहां था। लॉल – 0x499602D2

उत्तर

23

कारण यह है कि एक मानक एल्गोरिथ्म std::distance कहा जाता है, मौजूद है ADL (तर्क आश्रित लुक) द्वारा पाया जाता है है: भले ही आपके कॉल std नाम स्थान के साथ योग्य नहीं है, अपने तर्क a और b (यानी std::string) जीवन के प्रकार std::distance फ़ंक्शन (यानी std) के समान नामस्थान में, और इसलिए std::distance() को ओवरलोड रिज़ॉल्यूशन के लिए भी माना जाता है।

यदि आप वास्तव में अपने फ़ंक्शन को distance() (मैं आपको सुझाव देना चाहता हूं) को कॉल करना चाहता हूं, तो आप इसे अपने नाम के स्थान पर रख सकते हैं, और फिर इसे कॉल करते समय फ़ंक्शन नाम को पूरी तरह से अर्हता प्राप्त कर सकते हैं, या इसे छोड़ सकते हैं ग्लोबल नेम स्पेस और यह इस तरह से आह्वान:

::distance(a, b); 
// ^^ 

सूचना, तथापि, कि ADL अकेला हो सकता है नहीं कारण अपने कार्यक्रम संकलन स्टैंडर्ड लाइब्रेरी के अपने कार्यान्वयन iterator_traits के SFINAE के अनुकूल संस्करण प्रदान करता है, तो विफल (अधिक this Q&A on StackOverflow में विवरण - MooingDuck की सौजन्य)।

iterator_traits के SFINAE के अनुकूल कार्यान्वयन के साथ

, अपने संकलक पहचान करनी चाहिए कि std::distance() समारोह टेम्पलेट (क्योंकि यह एक टेम्पलेट है) जब दिए गए प्रकार std::string के तर्कों instantiated नहीं किया जा सकता है, इसकी वापसी प्रकार की वजह से:

template< class InputIt > 
typename std::iterator_traits<InputIt>::difference_type 
//  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
//  Trying to instantiate this with InputIt = std::string 
//  may result in a soft error during type deduction if 
//  your implementation is SFINAE-friendly, and in a hard 
//  error otherwise. 
    distance(InputIt first, InputIt last); 

इस मामले में, कंपाइलर अधिभार संकल्प के प्रयोजनों के लिए बस इस टेम्पलेट को त्याग देगा और अपना distance() फ़ंक्शन चुनें।

हालांकि, अगर स्टैंडर्ड लाइब्रेरी के अपने कार्यान्वयन iterator_traits के SFINAE के अनुकूल संस्करण प्रदान नहीं करता है, प्रतिस्थापन विफलता एक संदर्भ है कि SFINAE लिए योग्य नहीं है में हो सकता है, इस प्रकार एक (हार्ड) संकलन त्रुटि हो जाती है।

यह live example आपके मूल प्रोग्राम को जीसीसी 4.8.0 के साथ संकलित करता है, जो libstdC++ के संस्करण के साथ आता है जो एक SFINAE- अनुकूल iterator_traits लागू करता है।

+3

यदि यह नामस्थान std का उपयोग कर रहा है, तो यह केवल एक समस्या नहीं होनी चाहिए? –

+0

तो मुझे बस एक और नाम चुनना है? मेरे कार्य दूरी का नाम देने का कोई तरीका नहीं है? – egoard

+0

@egoard: मैं आपको एक और नाम चुनने का सुझाव दूंगा, हां। लेकिन यदि आप वास्तव में 'दूरी() 'रखना चाहते हैं, तो आप स्पष्ट रूप से संकलक को बताकर कॉल को अर्हता प्राप्त कर सकते हैं कि आप वैश्विक नामस्थान में कार्यरत दूरी' दूरी ') चाहते हैं (जैसा कि मेरे उत्तर में अंतिम संपादन में सुझाया गया है)) –

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