2012-06-28 8 views
11

Можно ли проверить, что тип является экземпляром определенного шаблона?Как проверить, является ли тип экземпляром данного шаблона класса?

У меня есть шаблон шаблона, где один из параметров шаблона должен быть либо экземпляром определенного шаблона, либо каким-либо другим типом. Например, рассмотрит это простое определение списка типов:

struct null_type; 

template <typename Head, typename Tail> 
struct typelist 
{ 
    // Tail must be a typelist or null_type 

    typedef Head head; 
    typedef Tail tail; 
}; 

Теперь я хотел бы, чтобы убедиться, что тип предназначен для параметра Tail шаблона всегда либо конкретизация typelist или null_type. Я мог бы использовать частичную специализацию, чтобы определить шаблон только для тех случаев, как это:

template <typename Head, typename Tail> 
struct typelist; // default, not defined 

template <typename Head, typename H, typename T> 
struct typelist< Head, typelist<H,T> > // Tail = typelist, ok 
{ 
    typedef Head head; 
    typedef typelist<H,T> tail; 
}; 

template <typename Head> 
struct typelist< Head, null_type > // Tail = null_type, ok 
{ 
    typedef Head head; 
    typedef null_type tail; 
}; 

Однако, я в конечном итоге дублирования кода, который является то, что я хотел бы избежать. В идеале, я бы нужна черта, чтобы проверить тип является ли конкретизацией шаблона, чтобы использовать его с enable_if или в статических утверждений:

#include <boost/mpl/or.hpp> 
#include <type_traits> 

struct null_type; 

template <typename Head, typename Tail> 
struct typelist 
{ 
    static_assert(
     boost::mpl::or_< 
      is_instantiation_of< typelist, Tail >, 
      std::is_same< Tail, null_type > 
     >::value, 
     "Tail must be a typelist or null_type"); 

    typedef Head head; 
    typedef Tail tail; 
}; 

ли такая черта (is_instantiation_of) уже доступны в стандартной библиотеке или в Boost? Можно ли написать одно?

ответ

17

я придумал следующее решением, с помощью C++ 11 VARIADIC шаблонов и простую частичную специализацию:

#include <type_traits> 

template < template <typename...> class Template, typename T > 
struct is_instantiation_of : std::false_type {}; 

template < template <typename...> class Template, typename... Args > 
struct is_instantiation_of< Template, Template<Args...> > : std::true_type {}; 

Это может быть адаптировано к C++ 03, используя препроцессор для создания версии для изменяющегося количество параметров шаблона, но возможно, более простой способ.

+0

Tch, я как раз собирался нажать «Опубликовать свой ответ». : P – Xeo

+0

@Xeo Я тоже! :( –

+5

Btw, я называю [мою версию] (https://bitbucket.org/martinhofernandes/wheels/src/default/include/wheels/type_traits.h%2B%2B#cl-161) 'is_specialization_of', потому что это Правильный термин для этого. «Инициация» - это * процесс * генерации «специализаций». –

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