2011-11-03 8 views
9

मुझे एक समस्या है जहां मुझे दो प्रकार के सामान्य पूर्वजों (एक या शून्य आधार वर्गों के साथ) की खोज करने की आवश्यकता है यदि यह मौजूद है। क्या इस समस्या को हल करने के लिए एक प्रकार का गुण बनाना संभव है? कोड में:संकलन समय पर, एक विरासत पेड़ की जड़ कैसे दो प्रकार के लिए आम है, यदि कोई मौजूद है?

template<typename T1, typename T2> 
    struct closest_common_ancestor 
{ 
    typedef XXX type; // what goes here? 
}; 

को देखते हुए निम्नलिखित प्रकार:

struct root {}; 
struct child1 : root {}; 
struct child2 : root {}; 
struct child3 : child2 {}; 
struct unrelated {}; 

closest_common_ancestor निम्नलिखित प्रकार में परिणाम होगा:

closest_common_ancestor<root, child1>::type == root 
closest_common_ancestor<child1, child2>::type == root 
closest_common_ancestor<child3, child1>::type == root 
closest_common_ancestor<child3, child2>::type == child2 
closest_common_ancestor<unrelated, child1>::type == error 

मेरा मानना ​​है कि मैं अगर मैं क्या एक निरीक्षण कर सकते हैं इस समस्या को हल कर सकते हैं प्रकार शून्य या एक बेस क्लास है, और यदि ऐसा है, तो उस प्रकार का नाम। क्या यह संभव है?

+2

आप बेस क्लास का निरीक्षण नहीं कर सकते हैं। जब तक कि आप अपनी प्रत्येक कक्षा में मेटा जानकारी मैन्युअल रूप से नहीं जोड़ते। –

+0

ध्यान दें कि प्रत्यक्ष संबंध के लिए यह पहले से ही संभव है ('is_base_of' को मूल सी ++ 03 ब्लॉक के संदर्भ में कार्यान्वित किया जा सकता है) –

+0

यदि 2 जड़ें' root1' और 'root2', और' child1', 'child2' वारिस हैं उनमें से दोनों ('struct child1: root1, root2 {};'), यह 'closest_common_ancestor' के लिए संदिग्ध होगा जो वापस आना है। – kennytm

उत्तर

7

जैसा कि के-बलो ने उल्लेख किया है कि दुर्भाग्य से दुर्भाग्यवश कक्षाओं की सूची प्राप्त करना असंभव है (बहुत बुरा ...)।

यदि आप मैन्युअल रूप से अपनी कक्षाओं को एनोटेट करते हैं (कहें, एक साधारण std::tuple<> आधारों को सूचीबद्ध करना), तो आप इस जानकारी का उपयोग कर सकते हैं।

template <typename> struct list_bases { typedef std::tuple<> type; }; 

तो फिर आप अपने प्रकार के लिए इस विशेषता के विशेषज्ञ कर सकते हैं::

template <> struct list_bases<child1> { typedef std::tuple<root> type; }; 

और वहाँ से शुरू है, तो आप एक पूर्वज पाने के साथ प्रयोग शुरू कर सकते हैं सरल, ज़ाहिर है, एक विशेषता का उपयोग किया जाएगा ... हालांकि यह तत्काल नहीं हो सकता है। कार्यान्वयन के विवरण के अलावा ("दूरी" चयन को लागू करने के आधार पर आधारों को दोबारा प्राप्त करना), मुझे "अजीब" मामलों के साथ एक समस्या की उम्मीद है।

struct root1 {}; struct root2 {}; 

struct child1: root1 {}; struct child2: root2 {}; 

struct child12: root1, child2 {}; struct child21: root2, child1 {}; 

अब, child12 और child21 दो आम पूर्वजों है:

दूरी चयन, हमेशा की तरह (लीनियर) वंशानुगत पदानुक्रम में is_base_of और is_same का एक संयोजन का उपयोग करके हल किया जा सकता है, तथापि निम्न पदानुक्रम पर विचार करें: root1 और root2 ... जो निकटतम है?

वे समकक्ष हैं। विचार करें कि मैं जोड़ें:

struct root3 {}; struct child31: root3, child1 {}; 

फिर root1child12, child21 और child31 के लिए एक आम पूर्वज है।

लेकिन अगर मैं closest_common_ancestor की परिभाषा पर skirted और मनमाने ढंग से परिभाषित किया गया है कि closest_common_ancesotr<child12, child21>root2 है, तो मैं नहीं किसी भी आम पूर्वज child31 साथ मिल सकता है।

इसलिए मेरा प्रस्ताव सभी निकटतम पूर्वजों की सूची है, और सेट ऑपरेशंस को लागू करने के लिए tuple का उपयोग करें।

+0

धन्यवाद। मेरे आवेदन के लिए मैं उस अस्पष्टता को हल करता हूं जिसका आप उल्लेख करते हुए उल्लेख करते हैं कि विचाराधीन सभी प्रकारों में केवल शून्य या एक आधार प्रकार है। –