2013-01-05 19 views
6

मुझे तर्क-निर्भर (कोएनिग) लुकअप के पीछे नियमों को समझने में परेशानी हो रही है।तर्क-निर्भर लुकअप - यह कब किया जाता है, क्या खोजा जाता है, और आप इसे कैसे रोक सकते हैं (या रोक सकते हैं)?

नीचे कोड पर विचार करें:

#include <iostream> 

using namespace std; 

namespace adl 
{ 
    struct Test { }; 
    void foo1(Test const &) { cout << "ADL used (foo1)" << endl; } 
    void foo2(Test const &) { cout << "ADL used (foo2)" << endl; } 
    void foo3(Test const &) { cout << "ADL used (foo3)" << endl; } 
} 

struct foo1 
{ 
    foo1() { } 

    template<class T> 
    foo1(T const &) { cout << "ADL not used (foo1)" << endl; } 

    template<class T> 
    void operator()(T const &) const { cout << "ADL not used (foo3)" << endl; } 
}; 

template<class T> void foo2(T const &) 
{ cout << "ADL not used (foo2)" << endl; } 

int main() 
{ 
    adl::Test t; 
    foo1 foo3; 
    (foo1(t)); 
    (foo2(t)); 
    (foo3(t)); 
} 

इसका उत्पादन होता है: इस्तेमाल किया

ADL नहीं (foo1)
ADL इस्तेमाल किया (foo2)
ADL इस्तेमाल नहीं किया (foo3)

मैं ई उन सभी को एडीएल का उपयोग करने का अनुमान लगाया, लेकिन मुझे आश्चर्य हुआ कि उनमें से कुछ ने ही किया था।

ADL के नियमों के पीछे क्या हैं (संभावित रक्तमय, मुझे पता है) विवरण?
मैं इस अवधारणा को काफी अच्छी तरह समझता हूं, लेकिन विवरण वह है जो मुझे परेशानी हो रही है।

कौन सा स्कॉप्स खोजे जाते हैं, उन्हें कब खोजा जाता है, और जब वे खोज नहीं जाते हैं?

यह बिल्कुल ADL कोड की दी गई लाइन से पहले सभी#include 'घ फ़ाइलों के माध्यम से देखने के लिए बिना प्रयोग किया जाता है कि क्या यह बताने के लिए संभव है? मुझे आशा है कि एडीएल मास्किंग के मामले में मज़दूरों और कार्यों का व्यवहार उसी तरह से व्यवहार न करें, लेकिन स्पष्ट रूप से वे नहीं करते हैं।

क्या बल एडीएल का कोई तरीका है जहां यह स्वचालित रूप से नहीं किया जाता है (जैसे ऊपर) और आप कक्षा के नामस्थान (उदा। टेम्पलेट में) नहीं जानते हैं?

+1

-1 यह प्रश्न बहुत व्यापक है, और कोड उदाहरण वास्तव में बेकार (भ्रामक नाम आदि के साथ) बेकार है। –

+1

मुझे यह नहीं मिला। आप '(foo3 (टी)) के साथ प्रयोग क्यों कर रहे हैं;'? 'Foo3' नामक कोई फ़ंक्शन नहीं है। तो एडीएल तस्वीर में नहीं आता है। 'foo3' को बिना किसी संदेह के ऑब्जेक्ट के रूप में माना जाएगा, क्योंकि यह वही है (जिसका अर्थ है कि यह बिना किसी संदेह के 'ऑपरेटर()' को कॉल करेगा)! यह सिर्फ आपके नाम में उपयोग किए जाने वाले भ्रामक नाम हैं। – Nawaz

+0

@ चीयर्संधथ-अल्फ: लेकिन '(foo3 (टी)) पर कोई भ्रम नहीं है; '। यह सिर्फ इतना है कि उन्होंने परिवर्तनीय के लिए भ्रामक नामों का उपयोग किया है! – Nawaz

उत्तर

5

आपकी समस्या वास्तव में तर्क निर्भर लुकअप के साथ नहीं है। सबसे पहले, तर्क निर्भर लुकअप केवल संभवतः तस्वीरों में प्रवेश करता है जब कार्यों की अयोग्य दिखता है। foo1(t)foo1 पर कॉल करते समय एक प्रकार और इसके टेम्पलेट कन्स्ट्रक्टर को कॉल किया जाता है। इसी प्रकार, foo3(t) एक योग्य खोज है क्योंकि foo3 एक ऑब्जेक्ट है और फ़ंक्शन कॉल ऑपरेटर ऑब्जेक्ट की कक्षा foo1 में देखा जाता है।

  1. ::foo2<adl::Test>(adl::Test const&)
  2. ::adl::foo2(adl::Test const&)

इन दोनों कार्यों को सौंपा जाता है संकल्प ओवरलोड और के बाद से दोनों कार्यों को समान रूप से कर रहे हैं: केवल जगह है जहाँ तर्क देखने चित्र में प्रवेश करती है जहां देखने उम्मीदवारों को पाता है foo2(t) बुला रहा है गैर-टेम्पलेट फ़ंक्शन जीतने से अच्छा मिलान होता है।

  1. नाम देखने के रक्तमय विवरण बहुत व्यापक हैं, और इस प्रकार इस सवाल का एक निबंध लिखा होना चाहिए जो मैं उपेक्षा के लिए एक अनुरोध है:

    आपका प्रश्न वास्तव में तीन सवाल कर रहे हैं।

  2. आपका दूसरा प्रश्न तीन और प्रश्नों तक फैला है, केवल एक ही प्रासंगिक लगता है:
    1. कौन सा स्कोप खोजे जाते हैं? फ़ंक्शन परिभाषा के अंदर एक अयोग्य फ़ंक्शन नाम को देखते समय नियम इस बात पर निर्भर करते हैं कि इनमें से कोई भी नाम एक आश्रित नाम है या नहीं। यदि ऐसा कोई नाम नहीं है (यानी, गैर-टेम्पलेट कोड में या टेम्पलेट कोड में जहां नाम चरण चरण में निर्धारित किए जा सकते हैं), नाम नामस्थानों को संलग्न करता है और इसके तर्क से जुड़े नामस्थानों में नाम देखा जाता है। अन्यथा, नाम केवल संबंधित नामस्थानों में देखा जाता है।
  3. क्या तर्क निर्भर लुकअप को मजबूर किया जा सकता है? यह हमेशा अयोग्य फ़ंक्शन लुकअप के लिए किया जाता है यदि कम से कम एक तर्क होता है लेकिन नाम अन्यथा बेहतर मिलान हो सकते हैं। बेशक, आपको एक अयोग्य समारोह को कॉल करने की आवश्यकता है अन्यथा यह नहीं किया जाएगा।
+0

अभी भी यह समझने की कोशिश कर रहा है कि कॉल "अयोग्य" कहलाता है। मैंने सोचा कि "अयोग्य" का अर्थ है "कोई क्वालीफायर [यानी नामस्थान] के साथ" ... लेकिन स्पष्ट रूप से यह मामला नहीं है, क्योंकि इनमें से कोई भी नामस्थान का उल्लेख नहीं करता है? कॉल के लिए अयोग्य होने का क्या अर्थ है? – Mehrdad

+0

जब नामों को देखा जाता है तो यह नाम पहले होता है और नाम मिलने पर बंद हो जाता है। 'foo1' एक प्रकार पाता है और प्रकार के संदर्भ में कॉल करने के लिए कन्स्ट्रक्टर को देखता है। चूंकि किसी फ़ंक्शन से पहले एक प्रकार पाया गया था, इसलिए कोई अन्य नामस्थान नहीं माना जाता है। इसी तरह 'foo3' के लिए जो एक ऑब्जेक्ट पाया जाता है जिसके लिए फ़ंक्शन कॉल ऑपरेटर ऑब्जेक्ट के प्रकार के सिंटटेक्स्ट में देखा जाता है। 'Foo2' के लिए एक फ़ंक्शन पाया जाता है और कॉल अयोग्य है, यानी, तर्कों से जुड़े नामस्थान ओवरलोड लोड को बढ़ाने के लिए खोजे जाते हैं। –

+0

यह * प्रक्रिया * का एक अच्छा वर्णन है कि संकलक निम्नानुसार है, लेकिन मुझे अभी भी समझ में नहीं आता कि "योग्य" क्या है। आप "एडीएल का कारण बनने वाले किसी भी कॉल" के रूप में योग्यता को परिभाषित कर रहे हैं, और फिर कह रहे हैं कि एडीएल केवल अयोग्य कॉल के लिए किया जाता है ... जो परिभाषा के अनुसार सच है, लेकिन यह समझने में मेरी सहायता नहीं करता कि कॉल क्या योग्य है। लेकिन क्या कॉल योग्यता प्राप्त करता है, बिल्कुल? मैं कैसे बता सकता हूं कि दिया गया कॉल योग्य है या नहीं? – Mehrdad