2011-02-03 4 views
22

मेरे विचार के लिए यहां कोड का एक छोटा सा टुकड़ा है जो मुझे बहुत पहेली बनाता है। अजीब चीज यह है कि यह सूर्य स्टूडियो और जीसीसी दोनों पर संकलित है, भले ही मुझे लगता है कि यह नहीं होना चाहिए।कक्षा तर्कों के साथ कार्य एक नामस्थान से लीक हो गए हैं?

इस पर विचार करें:

namespace name 
{ 
    class C 
    { 
     int a; 
    }; 

    void f(C c); 
    void g(int a); 
} 

int main(int argc, char** argv) 
{ 
    name::C c; 

    name::f(c); 
    f(c); // <--- this compiles, strangely enough 

    name::g(42); 
    // g(42); <--- this does not, as I expected 
} 

एक ही नाम स्थान से वर्ग तर्क नाम स्थान से बाहर 'रिसाव' के लिए समारोह f कारण बनता है और name:: बिना सुलभ हो।

क्या किसी के पास इसके लिए स्पष्टीकरण है? यह निश्चित रूप से मुझे है और संकलक यहां गलत नहीं है।

+0

दिलचस्प, बीटीडब्ल्यू इंटेल कंपाइलर (आईसीपीसी) इसे भी संकलित करता है ... – Artyom

+0

अप्रासंगिक बिट्स को हटाने के लिए अपना स्वयं का प्रश्न संपादित करें और उसी समस्या के साथ दूसरों को ढूंढना आसान बनाएं। – lytenyn

उत्तर

28

इसे argument-dependent lookup (या कोएनिग लुकअप) कहा जाता है। संक्षेप में, संकलक नामस्थानों में फ़ंक्शन की तलाश करेगा जो तर्क प्रकारों के नामस्थान हैं।

+1

धन्यवाद, यह एक सी ++ सुविधा है जिसे मैंने कभी नहीं सुना था .. – lytenyn

+5

@lytenyn: यह एक है जिसे आप हर रोज इस्तेमाल करते हैं :) 'std :: string s; एस + = "एए"; ', यहां' + = '' std' नेमस्पेस से आता है भले ही आपने इसे कभी निर्दिष्ट नहीं किया है, एडीएल के लिए धन्यवाद। –

+0

@ matthieu-m: निश्चित रूप से, बिल्कुल सही है, iostreams का उपयोग करते समय। लेकिन ये छोटी चीजें हैं जिनके बारे में आप कभी नहीं सोचते हैं जब तक कोई आपके नाक को इसमें धक्का नहीं देता है :) इसके अलावा, मुझे किसी भी सी ++ पुस्तक को याद नहीं किया जा सकता है जिसे मैंने कभी भी उल्लेख किया है, भले ही यह बहुत मौलिक है। यह निश्चित रूप से मेरी याददाश्त हो सकती है। लिंक के लिए – lytenyn

11

यह Argument-Dependent Name Lookup, a.k.a. ADL, a.k.a. Koenig लुकअप है। इस ऑपरेटरों काम करने के लिए आविष्कार किया गया था के रूप में उम्मीद, जैसे:

namespace fu { 
    struct bar { int i; }; 
    inline std::ostream& operator<<(std::ostream& o, const bar& b) { 
     return o << "fu::bar " << b.i; 
    } 
} 

fu::bar b; 
b.i = 42; 
std::cout << b << std::endl; // works via ADL magic 

ADL बिना आप करना होगा या तो स्पष्ट रूप भी भद्दा स्पष्ट कॉल बदसूरत using fu::operator<<; साथ उत्पादन ऑपरेटर लाने के लिए, या का उपयोग करें:

fu::operator<<(std::cout, b) << std::endl; 
+1

+1, इच्छा है कि आपने लेख को सारांशित किया हो। – Crisfole

+2

लेख बहुत छोटा है, आपकी जिज्ञासा कहां है? –

6

यह "तर्क निर्भर लुकअप" के कारण है। कॉन्स को हटाने से आप जो व्यवहार देख रहे हैं उसे बदल नहीं पाएंगे। प्रदर्शित करने के लिए है कि यह ADL है, नाम स्थान के सेंट struct के बाहर ले जाने का प्रयास ...

struct St 
{ 
    int a; 
}; 

namespace name 
{ 
    void f(const St& st); 
    void g(int a); 
} 

int main(int argc, char** argv) 
{ 
    St st; 

    name::f(st); 
    f(st); // <--- now you will get the expected compile error 

    name::g(42); 
    // g(42); <--- this does not, as I expected 
} 
1

कि तर्क निर्भर देखने के कारण होता है।

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