2012-10-17 22 views
11

मैंने भाग्य के साथ इसे गुगल करने की कोशिश की, इसलिए मैं यहां कोशिश कर रहा हूं।सी ++ पुनरावर्ती नेस्टेड प्रकार और नाम इंजेक्शन

मेरे पास कुछ कक्षाएं हैं, जिनमें से प्रत्येक सदस्य struct foo को परिभाषित करता है। यह सदस्य प्रकार foo स्वयं को पूर्व वर्गों में से एक से प्राप्त कर सकता है, इसलिए सदस्य प्रकार foo स्वयं प्राप्त कर सकता है।

मैं टेम्पलेट metaprogramming का उपयोग कर (देखें नीचे) नेस्ट foo प्रकार उपयोग करना चाहते हैं, लेकिन C++ नाम इंजेक्शन, समस्याओं का परिचय के रूप में ऊपरी foo प्रकार का नाम कम foo प्रकार में इंजेक्ट किया जाता है, और ऊपरी एक संकल्प लिया हो जाता है जब मैं चाहता हूँ निचले भाग तक पहुंचने के लिए, A::foo::foo का उपयोग करके कहें।

#include <type_traits> 

struct A; 
struct B; 

struct A { 
    struct foo; 
}; 

struct B { 
    struct foo; 
}; 

struct A::foo : B { }; 
struct B::foo : A { }; 

// handy c++11 shorthand 
template<class T> 
using foo = typename T::foo; 

static_assert(std::is_same< foo< foo<A> >, foo<B> >::value, 
       "this should not fail (but it does)"); 

static_assert(std::is_same< foo< foo<A> >, foo<A> >::value, 
       "this should fail (but it does not)"); 

FYI करें, मैं समारोह डेरिवेटिव को लागू कर रहा हूँ, foo व्युत्पन्न प्रकार है:

यहाँ एक उदाहरण है। उपर्युक्त स्थिति उदा। पाप/कॉस के साथ

टीएलडीआर: मैं foo<foo<A>>foo<B>, foo<A> पर कैसे प्राप्त करूं?

धन्यवाद!

उत्तर

1

यह वास्तव में एक स्वचालित समाधान नहीं है लेकिन समस्या हल करता है। आपके प्रकार बेस क्लास के लिए टाइपिफ़ प्रदान करते हैं, इस की अनुपस्थिति/उपस्थिति SFINAE के माध्यम से टाइप की गई है और नेस्टेड फू को या तो आधार के माध्यम से या सामान्य लुक-अप के माध्यम से पाया जाता है।

यदि आप अधिक स्वचालन की आवश्यकता है तो is_base_of के साथ ज्ञात आधारों की सूची देखने के लिए आप शायद has_base स्वचालित कर सकते हैं।

#include <type_traits> 
template <typename T> 
struct has_base 
{ 
    typedef char yes[1]; 
    typedef char no[2]; 

    template <typename C> 
    static yes& test(typename C::base*); 

    template <typename> 
    static no& test(...); 

    static const bool value = sizeof(test<T>(0)) == sizeof(yes); 
}; 

struct A { 
    struct foo; 
}; 

struct B { 
    struct foo; 
}; 

struct A::foo : B { typedef B base; }; 
struct B::foo : A { typedef A base; }; 

template<typename T, bool from_base = has_base<T>::value > 
struct foo_impl { 
    typedef typename T::base::foo type; 
}; 

template<typename T> 
struct foo_impl<T, false> { 
    typedef typename T::foo type; 
}; 

template<typename T> 
using foo = typename foo_impl<T>::type; 

static_assert(std::is_same< foo< foo<A> >::, foo<B> >::value, 
       "this should not fail (but it does)"); 

static_assert(std::is_same< foo< foo<A> >, foo<A> >::value, 
       "this should fail (but it does not)"); 
int main() 
{ 

    return 0; 
} 
+0

मेरे मन में कुछ इसी तरह की थी, लेकिन एक तरह से उम्मीद कर रही थी मैं एक व्युत्पन्न प्रकार के लिए सदस्य आधार प्रकार परिभाषित करने ... धन्यवाद एक बहुत वैसे भी से बचने के सकता है! – max

+0

@MaximeTournier जैसा कि मैंने कहा था: यदि अड्डों की सूची तय की गई है, तो आप उन्हें स्वचालित रूप से संभाल सकते हैं। कई विरासत के चेहरे में यह बहुत अजीब हो जाता है। – pmr

+0

समझ गया, लेकिन अड्डों की सूची दुख की बात नहीं है: -/ – max