Is it possible to check that a type is an instantiation of a particular template?
I have a class template where one of the template parameter must be either an instantiation of a particular template, or some other type. For instance, consider this simple definition of a typelist:
struct null_type;
template <typename Head, typename Tail>
struct typelist
{
// Tail must be a typelist or null_type
typedef Head head;
typedef Tail tail;
};
Now, I would like to make sure that the type provided for the Tail
template parameter is always either an instantiation of typelist
or null_type
. I could use partial specialization to define the template only for those cases, like this:
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;
};
However, I end up duplicating code, which is something I would like to avoid. Ideally, I'd need a trait to test whether a type is an instantiation of a template, to use it with enable_if
or in static assertions:
#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 such a trait (is_instantiation_of
) already available in the standard library or in Boost? Is is possible to write one?