2016-08-22 2 views
8

Данный класс MyClass с одним параметром шаблонаC++ параметр шаблона класса должен иметь определенный родительский класс

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

и другого класса MySecondClass с двумя параметрами шаблона.

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

То, что я хотел бы сделать, это ограничить MyClass, чтобы разрешить только T, который является производным типом MySecondClass. Я уже знаю, что нужно что-то вроде

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

Я просто не уверен, что положить в для ?, как я хочу, чтобы все возможные MySecondClass «с.

+0

Я редактировал вопрос. Если вы считаете, что это не правильно, пожалуйста, откиньте его назад. – NathanOliver

+0

Интересно, что такое упражнение. Как вы планируете использовать тот факт, что 'T' происходит от некоторого экземпляра' MyParentClass'? Как вы думаете, что вы можете делать с «T», зная это, что вы не могли бы сделать иначе? –

+2

Почему вы постоянно меняете вопрос? –

ответ

7

Вы можете использовать параметр шаблона шаблон для базового шаблона, а затем проверить, если T* могут быть преобразованы в некоторой 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

Ваша живая демонстрация не скомпилируется ... – Cornstalks

+3

@Cornstalks Я считаю, что это точка как 'int 'не выводятся из класса шаблонов MyParentClass' (поэтому' enable_if_t' терпит неудачу и гарантирует, что 'MyClass' не является частью разрешения перегрузки для MyClass '). – dfri

+0

@dfri: Ах, ты прав. Я неправильно понял. Комментарий к двум строкам, указывающий, что «компиляция не сработает здесь», помогла бы понять, что неудача является преднамеренной. – Cornstalks

3

Вы можете использовать собственный признак, чтобы проверить, является ли тип получен из шаблона. Затем используйте эту черту внутри 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

Смежные вопросы