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