2016-08-22 29 views
8

Biorąc to klasa MyClass z jednego parametru szablonuC++ parametr szablonu klasy musi mieć specyficzną klasę nadrzędną

template<typename T> 
class MyClass 
{ 
    //... 
}; 

i innej klasy MySecondClass z dwóch parametrów szablonu.

template<typename T, typename U> 
class MySecondClass 
{ 
    //... 
}; 

Co chciałbym zrobić, to ograniczyć MyClass aby umożliwić T który jest rodzajem pochodzi od MySecondClass tylko. Już wiem, że potrzebuję czegoś podobnego

template<typename T, typename = std::enable_if<std::is_base_of<MySecondClass<?,?>, T>::value>> 
class MyClass 
{ 
    //... 
} 

Nie jestem tylko pewien, co do wprowadzenia do ? jak chcę, aby umożliwić wszystkie możliwe MySecondClass „s.

+0

edytowany pytanie. Jeśli uważasz, że to nie jest poprawne, cofnij je. – NathanOliver

+0

Zastanawiam się nad punktem ćwiczenia. W jaki sposób zamierzasz wykorzystać fakt, że 'T' pochodzi od jakiegoś wystąpienia' MyParentClass'? Co sądzisz, że możesz zrobić to z "T" wiedząc o tym, że nie możesz zrobić inaczej? –

+2

dlaczego ciągle zmieniasz pytanie? –

Odpowiedz

7

Można użyć parametru szablonu szablonu dla szablonu bazowego, a następnie sprawdzić, czy T* można przekształcić w pewnym Temp<Args...>:

template <template <typename...> class Of, typename T> 
struct is_base_instantiation_of { 
    template <typename... Args> 
    static std::true_type test (Of<Args...>*); 
    static std::false_type test (...); 

    using type = decltype(test(std::declval<T*>())); 
    static constexpr auto value = type::value; 
}; 

Live Demo

+0

Twoja demonstracja na żywo nie może się kompilować ... – Cornstalks

+3

@Cornstalks Wierzę, że jest to punkt jako 'int 'nie pochodzą z klasy szablonu' MyParentClass' (stąd 'enable_if_t' kończy się niepowodzeniem i zapewnia, że' MyClass' nie jest częścią rozdzielczości przeciążania dla 'MyClass '). – dfri

+0

@dfri: Ach, masz rację. Źle przeczytałem. Komentarz na temat dwóch linii wskazujących, że "kompilacja się tu nie powiedzie" pomógłby wyjaśnić, że niepowodzenie jest zamierzone. – Cornstalks

3

Można użyć niestandardowego cechę, by sprawdzić, czy typ pochodzi z szablonu. Następnie użyj tę cechę wewnątrz static_assert:

#include <type_traits> 

template <template <typename...> class T, typename U> 
struct is_derived_from_template 
{ 
private: 
    template <typename... Args> 
    static decltype(static_cast<const T<Args...>&>(std::declval<U>()), std::true_type{}) test(
      const T<Args...>&); 
    static std::false_type test(...); 

public: 
    static constexpr bool value = decltype(test(std::declval<U>()))::value; 
}; 


template <typename T1, typename T2> 
struct MyParentClass 
{ 
}; 

template<typename T> 
struct MyClass 
{ 
    static_assert(is_derived_from_template<MyParentClass, T>::value, "T must derive from MyParentClass"); 
}; 


struct DerivedFromMyParentClass : MyParentClass<int, float>{}; 

struct Foo{}; 

int main() 
{ 
    MyClass<DerivedFromMyParentClass> m; 
    MyClass<Foo> f; 
} 

live example