9

मैं कोई वास्तविक स्थिति है जिसमें निम्न उदाहरण में संक्षेप किया जा सकता है:टेम्पलेट वर्गों के अस्पष्ट एकाधिक वंशानुक्रम

template< typename ListenerType > 
struct Notifier 
{ 
    void add_listener(ListenerType&){} 
}; 

struct TimeListener{ }; 
struct SpaceListener{ }; 

struct A : public Notifier<TimeListener> 
     , public Notifier<SpaceListener> 
{ 

}; 

struct B : TimeListener{ }; 

int main() 
{ 
    A a; 
    B b; 

    a.add_listener(b); // why is ambiguous? 

    return 0; 
} 

क्यों संकलक कि B एक TimeListener है को स्पष्ट नहीं है, और इसलिए ही संभव है अधिभार संकल्प Notifier<TimeListener>::add_listener(TimeListener&) है?

+4

आप 'का उपयोग कर सूचक के साथ अपने मुद्दों को हल कर सकते हैं :: add_listener; '(और दूसरा एक) 'स्ट्रक्चर ए' में। [डेमो] (http://coliru.stacked-crooked.com/a/6e43848691a4cfcb) – Jarod42

उत्तर

8

सदस्य नाम के लिए देखने के नियमों का कहना है कि अपने कोड अस्पष्ट है, क्योंकि नाम दो बेस वर्गों में पाया जाता है और इसलिए लुकअप सेट अमान्य है। आपको लुकअप सेट और विलय के सभी विवरणों से परिचित होने की आवश्यकता नहीं है; महत्वपूर्ण जानकारी यह है कि दोनों बेस क्लास की जांच की जाती है और नाम add_listener दोनों में पाया जाता है, जो अस्पष्टता पैदा करता है।

आसान आधार उन बेस क्लास नामों को A में उपयोग-घोषणाओं के साथ लाने के लिए आसान है। इसका मतलब है कि add_listener के दोनों संस्करणों, A में देखा जाता है बल्कि आधार वर्ग की तुलना में, इसलिए कोई मर्ज अस्पष्टता है:

struct A : public Notifier<TimeListener> 
     , public Notifier<SpaceListener> 
{ 
    using Notifier<TimeListener>::add_listener; 
    using Notifier<SpaceListener>::add_listener; 
    //plus any more base classes 
}; 

Live Demo

5

मानक संकेतक कंपाइलर प्रतीक को हल करने के लिए पर्याप्त स्मार्ट नहीं है - इस तथ्य के बावजूद इसे एक संदिग्ध ऑपरेशन के रूप में परिभाषित किया गया है, इस तथ्य के बावजूद कि आप इस उदाहरण में तर्कसंगत रूप से काम कर सकते हैं। आपका कंपाइलर शायद प्रतीक प्रतीकों की तलाश में है, न कि प्रोटोटाइप के लिए, दोनों संभावित प्रतीकों को ढूंढने के बाद।

आप संकलक को बता सकते हैं कि आप टेम्पलेट प्रतीकों को असंबद्ध करके दोनों प्रकारों को स्पष्ट रूप से स्वीकार करते हैं जिन्हें आप जानते हैं उन्हें स्वीकार किया जाना चाहिए। यह कंपाइलर को किसी भी फॉर्म को स्वीकार करने के लिए मिलेगा और फिर टेम्पलेट लागू करेगा। नीचे इसका एक उदाहरण है। मैं अपने कंप्यूटर पर वर्तमान में इस परीक्षण नहीं कर सकते, लेकिन अगर संकलक कठिनाई अपने मूल उदाहरण में प्रतीकों को हल कर रहा है यह काम करना चाहिए:

struct A : public Notifier<TimeListener> 
     , public Notifier<SpaceListener> 
{ 
    using Notifier<TimeListener>::add_listener; 
    using Notifier<SpaceListener>::add_listener; 
}; 
+6

ऐसा नहीं है कि संकलक पर्याप्त स्मार्ट नहीं है, मानक कहता है कि यह संदिग्ध है। – TartanLlama

+0

अच्छा बिंदु। मैंने परिभाषित अस्पष्टता को समाहित करने के लिए 'पर्याप्त स्मार्ट नहीं' के बारे में स्पष्ट करने की कोशिश की। – Pyrce

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