/ / Come posso verificare se un tipo è un'istanza di un determinato modello di classe? [duplicato] - c ++, modelli, meta-programmazione template

Come posso verificare se un tipo è un'istanza di un determinato modello di classe? [duplicato] - c ++, template, template-meta-programming

È possibile verificare che un tipo sia un'istanza di un modello particolare?

Ho un modello di classe in cui uno dei parametri del modello deve essere un'istanza di un modello particolare o un altro tipo. Ad esempio, considera questa semplice definizione di un dattilografo:

struct null_type;

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

typedef Head head;
typedef Tail tail;
};

Ora, vorrei assicurarmi che il tipo fornito per il Tail Il parametro template è sempre un'istanza di typelist o null_type. Potrei usare la specializzazione parziale per definire il modello solo per quei casi, come questo:

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;
};

Tuttavia, finisco per duplicare il codice, che è qualcosa che vorrei evitare. Idealmente, avrei bisogno di un tratto per testare se un tipo è un'istanza di un modello, per usarlo enable_if o in affermazioni statiche:

#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;
};

È un tale tratto (is_instantiation_of) già disponibile nella libreria standard o in Boost? È possibile scriverne uno?

risposte:

17 per risposta № 1

Ho trovato la seguente soluzione, usando i modelli variadic C ++ 11 e la semplice specializzazione parziale:

#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 {};

Potrebbe essere adattato a C ++ 03 utilizzando il preprocessore per generare versioni per un numero variabile di parametri del modello, ma esiste forse un modo più semplice.