8

पर विचार करें निम्नलिखित कोड:सी ++ अधिभार संकल्प नियमों में एक दोष?

#include <iostream> 

namespace ns1 
{ 
    struct A 
    { 
    }; 

    template <class T> 
    std::ostream& operator << (std::ostream& os, const T& t) 
    { 
     return os << "ns1::print" << std::endl; 
    } 
} 

namespace ns2 
{ 
    template <class T> 
    std::ostream& operator << (std::ostream& os, const T& t) 
    { 
     return os << "ns2::print" << std::endl; 
    } 

    void f (const ns1::A& a) 
    { 
     std::cout << a; 
    } 
} 


int main() 
{ 
    ns1::A a; 

    ns2::f (a); 

    return 0; 
} 

संकलन प्रति मानक के रूप में "अस्पष्ट अधिभार त्रुटि" के साथ विफल रहता है।

लेकिन क्यों? निश्चित रूप से ए के 'घर' नामस्थान में "समान रूप से अच्छा" ऑपरेटर प्राथमिकता लेना चाहिए? क्या ऐसा कोई तार्किक कारण नहीं है?

+8

तुम्हें क्या लगता है 'A' के" होम "नाम स्थान में कार्य बुला समारोह' खुद f' का नाम स्थान में कार्यों से प्राथमिकता दी जाती चाहिए? इस संदिग्ध होने के आसपास कोई रास्ता नहीं है। एक त्रुटि केवल समझदार चीज है। –

+0

क्योंकि जो भी नामस्थान से बनाया गया है, जानता है कि ए को मुद्रित किया जाना चाहिए? – cppalex

+8

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

उत्तर

10

यदि आप चाहते हैं namespace A में अधिभार पसंद किया जा करने के लिए की तुलना में आप यह वास्तव में बेहतर बनाने के लिए यह करने के लिए कुछ जोड़ने के लिए होगा। कहते हैं, यह एक टेम्पलेट बनाने के द्वारा:

namespace ns1 
{ 
    std::ostream& operator<<(std::ostream&, const A&); 
} 

अन्यथा, वहाँ वास्तव में है देखने के लिए क्यों एक नाम स्थान में एक समारोह टेम्पलेट एक और नाम स्थान में एक समारोह टेम्पलेट को प्राथमिकता दी जाएगी अगर दोनों बिल्कुल बराबर हैं कोई वैचारिक कारण। आखिरकार, के नेमस्पेस में फ़ंक्शन टेम्पलेट f के नामस्थान में फ़ंक्शन टेम्पलेट की तुलना में "बेहतर" क्यों होगा? f के कार्यान्वयनकर्ता को "बेहतर पता नहीं" चाहिए? फ़ंक्शन हस्ताक्षर पर पूरी तरह से निर्भर होने से इस मुद्दे को दूर किया जाता है।

0

आप ध्यान से संकलक त्रुटियों पढ़ते हैं, अस्पष्टता त्रुटि ns1 और ns2 में operator<< संस्करणों के बीच नहीं है, लेकिन ns1 से operator<<(os, const char*) इन्स्टेन्शियशन और namespace std से ठीक उसी अधिभार के बीच। बाद में std::ostream पर एडीएल द्वारा खींचा जा रहा है।

#include <iostream> 

namespace ns1 
{ 
    struct A {}; 

    std::ostream& operator << (std::ostream& os, const A& t) 
    { 
     return os << "ns1::print" << std::endl; 
    } 

    void f (const A& a) 
    { 
     std::cout << a; 
    }  
} 

int main() 
{ 
    ns1::A a; 
    f(a); // rely on ADL to find ns1::operator<<(os, A) 
} 
:

सबसे अच्छा तरीका एक ही नाम स्थान में ns1::A (जैसे f(A) के रूप में) से संबंधित सभी कार्यक्षमता जोड़ने के लिए @Barry, और de-templatize नाम स्थान ns1 में operator<< द्वारा की गई अनुशंसाओं का उपयोग करने के, लेकिन यह भी है

Live Example

नाम स्थान ns1 तो ADL के माध्यम से class A के व्यापक अंतरफलक के रूप में कार्य करता है।

+1

हां और नहीं। यदि आप चरित्र तारों से बाहर निकलते हैं, तो 'cout << a' अभी भी दो फ़ंक्शन टेम्पलेट्स – Barry

+0

के बीच संदिग्ध होगा, मैं इस ऑपरेटर को बदलने के लिए ओपी के उदाहरण को सरल बनाने के लिए प्रेरित हूं << (std :: ostream &, const t &) 'जी (कॉन्स टी एंड)' की तरह होना चाहिए। – Barry

+0

@ बेरी 'प्रिंट()' कुछ ऐसी आश्चर्यों को खत्म कर देगा, हां – TemplateRex

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