2012-08-29 20 views
6

Sınıf B'nin std :: vektöründen türetilmiş olup olmadığı nasıl derlenir?B sınıfının şablon ailesinden türetilmiş olup olmadığını sınama

template<class A> 
struct is_derived_from_vector { 
    static const bool value = ????; 
}; 

Sınıf B'nin şablon ailesinden türetilmiş olup olmadığını derleme zamanında nasıl test edilir?

template<class A, template<class> class Family> 
struct is_derived_from_template { 
    static const bool value = ????; 
}; 

kullanma:

template<class T> struct X {}; 

struct A : X<int> {} 
struct B : std::vector<char> {} 
struct D : X<D> {} 

int main() { 
    std::cout << is_derived_from_template<A, X>::value << std::endl; // true 
    std::cout << is_derived_from_template<D, X>::value << std::endl; // true 
    std::cout << is_derived_from_vector<A>::value << std::endl; // false 
    std::cout << is_derived_from_vector<B>::value << std::endl; // true 
} 
+4

, bir C++ sadece 03 ya da C++ 11 çözüm iyidir gerekip gerekmediğini bunu açık hale getirmek için önemlidir (Ben her ne kadar emin C++ 11 burada yardımcı olabilir) . Ve akıllıca bir açıklama olarak, asla standart kaplardan miras kalmamanız gerektiğine göre, orijinal özellik basittir: 'false': P –

+0

C++ 03. Msvc 2010 derleyicisini kullanıyorum. Bu nedenle ek olarak 'decltype' kullanmayı kabul ediyorum. std :: vector' örneğin ony’dır. C++ 03 çözümünü bilmiyorsanız, C++ 11 çözümü de kabul edilir. –

cevap

12

bu deneyin:

#include <type_traits> 

template <typename T, template <typename> class Tmpl> // #1 see note 
struct is_derived 
{ 
    typedef char yes[1]; 
    typedef char no[2]; 

    static no & test(...); 

    template <typename U> 
    static yes & test(Tmpl<U> const &); 

    static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes); 
}; 

Kullanımı: doğrultusunda#1 işaretlenmiş, yapabilirsin: Not

#include <iostream> 

template<class T> struct X {}; 

struct A : X<int> {}; 

int main() 
{ 
    std::cout << is_derived<A, X>::value << std::endl; 
    std::cout << is_derived<int, X>::value << std::endl; 
} 

Ayrıca özellik writint tarafından herhangi en az birine sahiptir şablonu, ama muhtemelen daha fazla tip argümanları kabul ettirmek:

Ben sınıf bir vektör elde edilir eğer böyle (bilmesi gereken aynı durum vardı
template <typename, typename...> class Tmpl 
+0

"Şablon sınıfı Tmpl" işlevini kullanır ve sınama işleviniz için bir parametre paketi kullanırsanız, bir şablonu yalnızca bir değil de herhangi bir sayıdaki argümanla işleyebilmeniz gerekir. –

+1

Bu yaklaşımdaki sorun, yalnızca tek bir argümanı olan şablonlar için çalışacak olmasıdır. * Std :: vector'nın * her zamanki * iki argümanını almak için onu artırırsanız bile, uygulamanın fazladan şablon parametreleri eklemesine izin verilir (bu parametreler için varsayılan değerler sağladığı sürece), bu yüzden% 100 taşınabilir olmayacaktır –

+1

@ DavidRodríguez-dribeas: Evet, bunu değişken yapınız ... –

1

)-sınıf. Maalesef projemde C++ - 11 veya varadik makrolar bulunmuyor. Yani benim çözüm Kerrek's answer bir karışımı ve sonunda bazı googletest-kodu ile bu article oldu:

#include <vector> 

template <typename T> 
class is_derived_from_vector 
{ 
    typedef char Yes_t[1]; 
    typedef char No_t[2]; 

    static No_t& test(const void* const); 

    template <typename U> 
    static Yes_t& test(const std::vector<U>* const); 

public: 
    static const bool value = ((sizeof(test(static_cast<T*>(0)))) == (sizeof(Yes_t))); 
}; 

template<class T> struct X {}; 
struct A : X<int> {}; 
struct B : std::vector<char> {}; 

TEST(Example, IsDerivedFrom) 
{ 
    EXPECT_FALSE(is_derived_from_vector<A>::value); 
    EXPECT_TRUE(is_derived_from_vector<B>::value); 
} 

Ben C++ kullanımı olmadan tanımlamak mümkün olmazdı düşünüyorum herhangi şablonları için ortak bir çözüm - 11 ya da daha yüksek.

0

Ben uzun zaman önce bu soruna bir çözüm arıyordu ve

Modern C++ Tasarım danıştıktan sonra: Uygulanan Genel Programlama ve Tasarım Kalıpları

ben takip oluşturmak başardı hangi yorumlarda sunulanlara daha çok veya daha az benzer.

şablon metaprogramlama ile
#include <iostream> 
#include <type_traits> 
#include <utility> 

template <typename T, template <typename...> class U> 
struct is_derived 
{ 
private: 
    template <typename...Ts> 
    static constexpr std::true_type check(const U<Ts...>&); 
    static constexpr std::false_type check(...); 


    template <typename> 
    struct is_same 
    { 
     static constexpr bool value = false; 
    }; 

    template <typename...Ts> 
    struct is_same <U<Ts...>> 
    { 
     static constexpr bool value = true; 
    }; 

    public: 
    static constexpr bool value = 
     std::is_same<decltype(check(std::declval<T>())), 
        std::true_type>::value && 
     !is_same<T>::value; 
}; 

template <typename, typename> 
struct X 
{ 
}; 

template <typename T> 
struct Y : X <T, int> 
{ 
}; 


int main(int argc, char **argv) { 

    std::cout << std::boolalpha << is_derived<Y<int>, X>::value << std::endl; 
    std::cout << std::boolalpha << is_derived<X<int,int>, X>::value << std::endl; 
    std::cout << std::boolalpha << is_derived<int, X>::value << std::endl; 

    return 0; 
} 
İlgili konular