2011-04-18 17 views
8

यह जीसीसी 4.4 के साथ संकलित करने में विफल क्यों होता है?नामस्थानों में फ़ंक्शन टेम्पलेट्स ओवरलोडिंग

template<typename T> 
class A { 
public: 
    void foo() { 

    } 

private: 
    T x; 
}; 

namespace Ns { 
template<typename T> 
void do_it (A<T> a) { 
    a.foo(); 
} 
}; 

template<typename T> 
void myfun (T x) { 
    Ns::do_it (x); 
} 

template<typename T> 
class B { 
public: 
    void bar() { 

    } 

private: 
    T x; 
}; 

namespace Ns { 
template<typename T> 
void do_it (B<T> b) { 
    b.bar(); 
} 
}; 

int main() { 
    A<int> a; 
    B<int> b; 

    myfun (a); 
    myfun (b); // error: no matching function call to do_it(B<int>&) 

    return 0; 
} 

यह do_it का नाम स्थान के साथ कुछ होना आवश्यक है। जब मैं इसके आस-पास नामस्थान हटा देता हूं, तो यह संकलित होता है।

पृष्ठभूमि: मैं फ़ंक्शंस का एक सेट बना रहा हूं जिसका उपयोग कई अलग-अलग कंटेनर वर्गों के साथ किया जा सकता है। अलग-अलग इंटरफ़ेस को समान रूप से संभालने के लिए मैं फ्रीस्टैंडिंग फ़ंक्शंस का उपयोग करता हूं जो प्रत्येक कंटेनर कक्षाओं के लिए अधिभारित होते हैं। उनके साथ वैश्विक नामस्थान को छेड़छाड़ से बचने के लिए इन कार्यों को नामस्थान में रखा जाएगा।

बी के लिए परिभाषाओं को ए के लिए अलग-अलग शीर्षलेख फ़ाइल से आने के बारे में सोचा जाएगा, इसलिए एक पुनर्वितरण एक विकल्प नहीं है।

+0

यह एक टाइपो है! HTML द्वारा निगल लिया गया था। –

+0

वीएस 2010 उपर्युक्त कोड संकलित करता है, और मेरा मानना ​​है कि ऐसा करने में यह सही है, लेकिन यह एक मुश्किल उदाहरण है। अच्छा प्रश्न! –

+0

वीएस -2008 के साथ ही, मैंने अभी इसे चेक किया है। क्या यह जीसीसी में एक बग हो सकता है या उनकी व्याख्या माइक्रोसॉफ्ट से अलग है? तथ्य यह है कि यह नामस्थान के बिना काम करता है यह एक बग होने के लिए इंगित करेगा, है ना? –

उत्तर

6

कारण यह है कि कॉल के बिंदु पर केवल एडीएल किया जाता है। अन्य फ़ंक्शन लुकअप केवल myfun फ़ंक्शन टेम्पलेट की परिभाषा में किए जाते हैं।

और उस परिभाषा संदर्भ में, केवल do_itA<int> को स्वीकार करने वाले अधिभार घोषित किया गया है।

संपादित करें: यदि आप इसके लिए मानक संदर्भ चाहते हैं, तो [temp.dep.candidate] और [temp.res] p1 देखें।

+0

क्या नामस्थानों का उपयोग करके इसे हल करने का कोई मानक तरीका है? –

+2

@ मार्क अगर आप नामस्थान 'एनएस' में फ़ंक्शंस रखना चाहते हैं, तो आप उस नामस्थान में परिभाषित डमी क्लास से 'बी ' प्राप्त कर सकते हैं, ताकि एडीएल 'एनएस' नेमस्पेस को देख सके। या आप 'बी ' पर टेम्पलेट तर्कों को पास कर सकते हैं जो जेनरेट विशेषज्ञता को 'एनएस' से जोड़ते हैं। उदाहरण के लिए 'बी <एनएस :: ADLAssociator >' (ADLAssociator केवल एक छोटा वर्ग टेम्पलेट हो सकता है जो केवल 'टी टी' संग्रहित करता है)। या आप उन सहयोगी वर्गों को अतिरिक्त डमी तर्क के रूप में पास करते हैं: 'बी '। इस के लिए कई विकल्प हैं। ऐसा लगता है कि एक वर्ग से 'बी' प्राप्त करना या इसे 'एनएस' में परिभाषित करना सबसे साफ है। –

+5

एक स्थिर वर्ग सदस्य में नि: शुल्क फ़ंक्शन को बदलने के बारे में क्या: 'नेमस्पेस एनएस {टेम्पलेट संरचना प्रेषण; } '(इसे आगे घोषित करें), फिर प्रत्येक नए प्रकार के लिए, एक विशेषज्ञता जोड़ें: 'नेमस्पेस एनएस {टेम्पलेट संरचना प्रेषण < B> {स्थिर शून्य do_it (बी x) {x.bar()}}; } ', और' टेम्पलेट शून्य myfunc (टी टी) {एनएस :: प्रेषण :: do_it (टी); } ' –

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