È 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 № 1Ho 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.