2012-10-17 19 views
11

hiçbir şans ile bu googling çalıştı iç içe ++ yüzden buraya çalışıyorum.c yinelemeli türleri ve adı enjeksiyonu

bir elemanı struct foo tanımlayan her biri sınıfları, bir çift var. Bu üye türü foo kendisi dolayısıyla elemanı tipi foo kendisi elde edilmesi, eski sınıflarının birinden devralabilir.

(aşağıya bakın) şablonu metaprogramming kullanılarak iç içe foo türlerini erişmek istiyorum, ama üst foo tür adı alt foo türü içine enjekte alır gibi C++ adı enjeksiyon, sorunları tanıtır ve istediğim zaman Üstteki çözüme kavuşturulacağını Aşağıya erişmek için A::foo::foo'u kullanın. Bilginize, ben işlev türevleri uygulayarak ediyorum

#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)"); 

, foo türevi aşağıdaki gibidir: Burada

bir örnektir. Yukarıdaki durum örn. günah ile/cos.

TLDR: foo<A>, foo<B> olmak üzere foo<foo<A>>'u nasıl alabilirim?

Teşekkürler!

cevap

1

Bu gerçekten bir otomatik çözüm değildir ama sorunu çözer. İşletme tür temel sınıf, bu Typedef varlığının/yokluğunun SFINAE aracılığıyla tespit edilir ve iç içe foo baz ile ya da normal bir görünüm-up ile ya bulunduğunda bir typedef sağlar.

Daha fazla otomasyona ihtiyacınız varsa, is_base_of ile tabanlarının bir listesini kontrol etmek için has_base otomasyonunu otomatikleştirebilirsiniz.

#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

Aklımda benzer bir şey vardı, ama tür bir sürü neyse ... Her türetilmiş türü için Teşekkür üye tabanı türünü tanımlayan önlemek umuyordum! bazlar listesi sabit ise, bunları otomatik olarak işleyebilir: Dediğim gibi – max

+0

@MaximeTournier. Birden fazla kalıtım karşısında bu oldukça garipleşiyor. – pmr

+0

Anladım ama üsleri liste ne yazık ki sabit değildir: -/ – max