/ / Як я можу перевірити, чи тип є інстанцією заданого шаблону класу? [дублювати] - c ++, шаблони, шаблон-мета-програмування

Як перевірити, чи тип - це екземпляр певного шаблону класу? [дублікат] - c + +, шаблони, шаблон-мета-програмування

Чи можна перевірити, що тип - це екземпляр певного шаблону?

У мене є шаблон класу, де одним із параметрів шаблону має бути або інстанція певного шаблону, або інший тип. Наприклад, розглянемо це просте визначення набору:

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 за відповідь № 1

Я придумав таке рішення, використовуючи 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 за допомогою препроцесора для генерації версій для різного числа параметрів шаблону, але може бути й простий спосіб.