के आधार पर तर्क-निर्भर लुकअप मेरे पास एक टेम्पलेट क्लास 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
परीक्षण संकलित करने के लिए खुश है।
व्यावहारिक दृष्टिकोण में मेरी उदाहरण में कहें, तो आप सोच सकते हैं act
boost::intrusive_ptr
की एक विधि था कि, add_ref(A*)
intrusive_ptr_add_ref(CBase*)
था और B
आधार CBase
से पाने के लिए कुछ टेम्पलेट था।
कर रहा हूँ मैं सही है कि
clang
के अपने परीक्षण कार्यक्रम को खारिज सही है, औरgcc
औरComeau
मानक का पालन नहीं करते:इस मैं कई सवाल है के बारे में?
क्या कोई कारण है कि मानक ऐसे अव्यवहारिक व्यवहार को निर्दिष्ट करता है (टेम्पलेट क्लास बेस को संबंधित नेमस्पेस के रूप में अस्वीकार करता है)?
clang
3.4.2/3
के आधार परusing NA::add_ref
निर्देश के साथ मेरे परीक्षण कार्यक्रम को स्वीकार कर रहा है?क्या मुझे एक बग की रिपोर्ट करनी चाहिए? :)
पीएस मैंने clang Language Compatibility FAQ पढ़ा है और वहां कोई जवाब नहीं मिला है।
क्या सी ++ 11 मोड मदद करता है? सी ++ 11 ने शब्द को स्पष्ट किया है, क्योंकि वास्तव में 'एनबी :: बी' एक वर्ग है (जो एक टेम्पलेट विशेषज्ञता होता है), टेम्पलेट नहीं। (नियम, आईआईयूसी, यह है कि जिस प्रकार के टेम्पलेट से संबंधित नाम हैं, वे वर्ग से जुड़े नामस्थानों में * जोड़ा * हैं।) –
क्या यह बहुत नाजुक नहीं होगा? किसी बिंदु पर आप शायद 'add_ref' का एक डिफ़ॉल्ट कार्यान्वयन जोड़ते हैं जो हमेशा प्रत्यक्ष आधार के संबंधित नामस्थान से बेहतर मिलान होगा? – pmr
@ ल्यूकडैंटन, आप सही हैं। दोनों बिंदु (लगभग 'वर्ग' और' टेम्पलेट-आईडी' के संबंधित नामस्थान) वर्ग 'टेम्पलेट-आईडी' पर लागू होते हैं। –