2011-03-22 14 views
5

यह मेरे लिए पीछे की ओर एक छोटे से लगता है, लेकिन यह काम करता है:सी ++ पैरामीटर स्कोप नामस्थान के भीतर फ़ंक्शन लुकअप को क्यों प्रभावित करता है?

#include <iostream> 

namespace nTest 
{ 
    struct cTest {}; 

    void fTest(cTest& x) 
    { 
    std::cout << "nTest::fTest(cTest&) called" << std::endl; 
    } 
} 

int main(void) 
{ 
    nTest::cTest x; 
    fTest(x); //Weird! fTest is resolved since its parameter belongs to nTest. 
    return 0; 
} 

आम तौर पर, आप nTest की आवश्यकता होगी :: FTEST तक पहुँचने के लिए है, लेकिन इसकी पैरामीटर जो nTest के अंतर्गत आता है संभव की सूची में nTest जोड़ने के लिए प्रकट होता है स्कोप्स जिसमें fTest की खोज करने के लिए। यह मेरे लिए अजीब लगता है कि पैरामीटर स्कोप फंक्शन लुकअप को प्रभावित करता है।

यह जीसीसी में ठीक है, लेकिन मुझे आश्चर्य है कि यह उपयोग पोर्टेबल है? इस स्कोपिंग तंत्र की आधिकारिक परिभाषा क्या है?

+2

एडीएल - तर्क आश्रित लुकअप (http://en.wikipedia.org/wiki/Argument-dependent_name_lookup) – Nim

+2

स्वीकार्य उत्तर भी पढ़ें [यहां] (http://stackoverflow.com/questions/2958648/what-are -the-pitfalls-of-adl) –

उत्तर

2

यह कोएनिग उर्फ ​​तर्क निर्भर देखने http://en.wikipedia.org/wiki/Argument-dependent_name_lookup

+0

धन्यवाद! ठीक वही जो मेरे द्वारा खोजा जा रहा था। – Andrew

+0

@Andrew, अगर आपको आवश्यकता है तो कृपया उत्तर स्वीकार करें (वोट गिनती के तहत चेक मार्क पर क्लिक करें) – Nim

1

यह मूल रूप से, अतिभारित ऑपरेटरों को खोजने के लिए डिजाइन किया गया था ऑपरेटर < < आप एसटीडी :: अदालत एक स्ट्रिंग भेजने के लिए इस्तेमाल की तरह कहा जाता है। अगर हमारे पास एडीएल नहीं था, तो आपको इसके बजाय अपना कोड लिखना होगा: std::operator<<(std::cout, "nTest::fTest(cTest&) called")

बहुत अच्छा नहीं है!

और यदि यह ऑपरेटरों के लिए काम करता है, तो फ़ंक्शंस के लिए एक ही तरीके से क्यों काम नहीं करते?

12

वह एडीएल (तर्क आश्रित लुकअप) या कोएनिग लुकअप (सुविधा के डिजाइनर के लिए) है। सुविधा का उद्देश्य यह है कि कई मामलों में एक ही नामस्थान में प्रकार और कार्य शामिल होंगे जिन्हें उन प्रकारों पर लागू किया जा सकता है, जिनमें से सभी interface का पालन करते हैं। यदि एडीएल जगह पर नहीं था, तो आपको पहचानकर्ताओं को using घोषणाओं के साथ दायरे में लाना होगा या आपको कॉल अर्हता प्राप्त करनी होगी।

यह एक दुःस्वप्न बन जाता है क्योंकि भाषा ऑपरेटर ओवरलोड के लिए अनुमति देती है। निम्न उदाहरण पर विचार करें:,

namespace n { 
    struct test {}; 
    test operator+(test, test const &); // implemented 
}; 
int main() { 
    n::test a,b; 
    n::test c = a + b; //without ADL: c = n::operator+(a, b) 
} 

यह एक अजीब स्थिति की तरह लग सकता है पर विचार करें कि nstd नाम स्थान हो सकता है, testostream हो सकता है, और operator+operator<< हो सकता है:

int main(int argc, char**) { 
    std::cout << "Hi there, there are " << argc << " arguments" << std::endl; 
} 

ADL बिना , operator<< पर कॉल स्पष्ट होना चाहिए, और इसके अलावा आपको यह जानना होगा कि उनमें से कौन सा एक विधि बनाम एक फ्री फ़ंक्शन के रूप में लागू किया गया है। क्या आप जानते हैं कि std::cout << "Hi" एक नि: शुल्क फ़ंक्शन कॉल कर रहा है और std::cout << 5 सदस्य फ़ंक्शन को कॉल कर रहा है? बहुत से लोग इसे महसूस नहीं करते हैं, और गंभीरता से, लगभग कोई भी परवाह नहीं करता है। एडीएल आपके द्वारा छुपाता है।

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