2012-07-23 20 views
8

के आधार पर तर्क-निर्भर लुकअप मेरे पास एक टेम्पलेट क्लास NB::B<T> एक गैर-टेम्पलेट वर्ग NA::A से नामस्थान में व्युत्पन्न है। act<T> एक टेम्पलेट फ़ंक्शन है जो अपने टेम्पलेट तर्क के उदाहरण पर add_ref फ़ंक्शन को कॉल करता है। विशेष रूप से, act<NB::B<int>>add_ref को NB::B के आधार पर एडीएल का उपयोग करके परिभाषित करना चाहता है। पूर्ण उदाहरण निम्नलिखित है:टेम्पलेट वर्ग

template<class T> 
void act() { 
    T* p = 0; 
    add_ref(p); // the failing line 
} 

namespace NA 
{ 
    struct A { }; 

    // I want ADL to find this: 
    void add_ref(A* p) { 
    } 
} 

namespace NB 
{ 
    // template class with non-template base 
    template <class T> 
    struct B: NA::A { }; 

    typedef B<int> Bi; 

    // using NA::add_ref; // fixes the problem 
} 

int main() 
{ 
    act<NB::Bi>(); 
} 

यह gcc (4.7.0) में ठीक संकलित करता है। और Comeau ऑनलाइन में। हालांकि clang (3.1) में विफल रहता है:

a.cpp:4:3: error: use of undeclared identifier 'add_ref' 

इसी समय, मानक पढ़ता है:

3.4.2/2 ...

- टी एक टेम्पलेट आईडी है, तो उसके संबंधित नामस्थान और कक्षाएं नामस्थान हैं जिसमें टेम्पलेट परिभाषित किया गया है; सदस्य टेम्पलेट्स के लिए, सदस्य टेम्पलेट की कक्षा; टेम्पलेट प्रकार पैरामीटर के लिए प्रदान किए गए टेम्पलेट तर्कों के प्रकार से जुड़े नामस्थान और वर्ग (टेम्पलेट टेम्पलेट पैरामीटर को छोड़कर); नामस्थान जिसमें कोई टेम्पलेट टेम्पलेट तर्क परिभाषित किया गया है; और कक्षाएं जिनमें टेम्पलेट टेम्पलेट तर्क के रूप में उपयोग किए जाने वाले किसी सदस्य टेम्पलेट को परिभाषित किया गया है।

आश्चर्य की बात है कि, टेम्पलेट के आधार संबंधित नामस्थानों के पथ के रूप में सूचीबद्ध नहीं हैं। इस प्रकार clang का व्यवहार सही प्रतीत होता है। और Comeau और gcc गलत प्रोग्राम स्वीकार कर रहे हैं।

इसी समय, 3.4.2/3 कहा गया है कि बहस के नामस्थान में using की कोई असर नहीं:

जब एक संबद्ध नाम स्थान पर विचार, देखने प्रदर्शन किया, जब जुड़े नाम स्थान के रूप में प्रयोग किया जाता है देखने के रूप में ही है एक क्वालीफायर (3.4.3.2) को छोड़कर:

- संबंधित नामस्थान में किसी भी उपयोग-निर्देश को अनदेखा कर दिया जाता है।

लेकिन जब मैं using NA::add_ref लाइन uncomment clang परीक्षण संकलित करने के लिए खुश है।

व्यावहारिक दृष्टिकोण में मेरी उदाहरण में कहें, तो आप सोच सकते हैं actboost::intrusive_ptr की एक विधि था कि, add_ref(A*)intrusive_ptr_add_ref(CBase*) था और B आधार CBase से पाने के लिए कुछ टेम्पलेट था।

  1. कर रहा हूँ मैं सही है कि clang के अपने परीक्षण कार्यक्रम को खारिज सही है, और gcc और Comeau मानक का पालन नहीं करते:

    इस मैं कई सवाल है के बारे में?

  2. क्या कोई कारण है कि मानक ऐसे अव्यवहारिक व्यवहार को निर्दिष्ट करता है (टेम्पलेट क्लास बेस को संबंधित नेमस्पेस के रूप में अस्वीकार करता है)?

  3. clang3.4.2/3 के आधार पर using NA::add_ref निर्देश के साथ मेरे परीक्षण कार्यक्रम को स्वीकार कर रहा है?

  4. क्या मुझे एक बग की रिपोर्ट करनी चाहिए? :)

पीएस मैंने clang Language Compatibility FAQ पढ़ा है और वहां कोई जवाब नहीं मिला है।

+0

क्या सी ++ 11 मोड मदद करता है? सी ++ 11 ने शब्द को स्पष्ट किया है, क्योंकि वास्तव में 'एनबी :: बी ' एक वर्ग है (जो एक टेम्पलेट विशेषज्ञता होता है), टेम्पलेट नहीं। (नियम, आईआईयूसी, यह है कि जिस प्रकार के टेम्पलेट से संबंधित नाम हैं, वे वर्ग से जुड़े नामस्थानों में * जोड़ा * हैं।) –

+0

क्या यह बहुत नाजुक नहीं होगा? किसी बिंदु पर आप शायद 'add_ref' का एक डिफ़ॉल्ट कार्यान्वयन जोड़ते हैं जो हमेशा प्रत्यक्ष आधार के संबंधित नामस्थान से बेहतर मिलान होगा? – pmr

+0

@ ल्यूकडैंटन, आप सही हैं। दोनों बिंदु (लगभग 'वर्ग' और' टेम्पलेट-आईडी' के संबंधित नामस्थान) वर्ग 'टेम्पलेट-आईडी' पर लागू होते हैं। –

उत्तर

6

n3337, जो मूल रूप से नाबालिग संपादकीय परिवर्तन के साथ सी ++ 11 से, 3.4.2/2 पढ़ता है:

समारोह कॉल में शामिल प्रत्येक तर्क प्रकार टी के लिए [...] के सेट नामस्थान और वर्गों निम्नलिखित तरीके से निर्धारित कर रहे हैं: [...]

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

और यह तो मूलतः एक ही बोली हैं कि विवादित पोस्ट के साथ जारी है। यहां महत्वपूर्ण अंतर और है, जिसका अर्थ है कि आपने जो सूची उद्धृत की है (और मैंने छोड़ा है) पहले से ही निर्दिष्ट नामस्थानों के अतिरिक्त है, और इसमें नामस्थान शामिल हैं जिनमें से बेस क्लास सदस्य है।

  1. जीसीसी और आउला सही हैं, और कोड को अस्वीकार करने में क्लैंग ++ गलत है।

  2. < लागू नहीं होता>

  3. बजना ++ using NA::add_ref बिना यह खारिज करने में गलत है।

  4. हां, आपको शायद एक बग की रिपोर्ट करनी चाहिए। ऐसा लगता है कि यह पहले से ही रिपोर्ट और तय किया गया है।

+1

वह बग पहले से ही कुछ समय पहले और तय किया गया था। ज़हर बग था थैग क्लैंग ने अपने बेस क्लास (और इसके मित्र घोषणाओं) को खोजने के लिए टेम्पलेट को निष्क्रिय नहीं किया था –

+0

धन्यवाद, @ डेविड-रॉड्रिगेज-ड्राईबीस। वह 'आगे' मुद्दे को स्पष्ट करता है। –

+0

@ जोहान्स-schaub-litb, किसी भी मौके पर आपको उस बग का लिंक याद है जिसके बारे में आप बात कर रहे हैं? मैंने अभी इसे 'क्लैंग' ट्रंक के ताजा निर्माण पर जांच लिया है और बग अभी भी मौजूद है। –

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