Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if a type is an instantiation of a given class template? [duplicate]

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?

like image 860
Luc Touraille Avatar asked Jun 28 '12 19:06

Luc Touraille


People also ask

What is the instantiation of the class template?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation.

How the instantiation of function template happens?

When a function template is first called for each type, the compiler creates an instantiation. Each instantiation is a version of the templated function specialized for the type. This instantiation will be called every time the function is used for the type.

How do I instantiate a class template in C++?

To instantiate a template class explicitly, follow the template keyword by a declaration (not definition) for the class, with the class identifier followed by the template arguments. template class Array<char>; template class String<19>; When you explicitly instantiate a class, all of its members are also instantiated.

What is the difference between template class and template Typename?

2: There is no semantic difference between class and typename in a template-parameter. typename however is possible in another context when using templates - to hint at the compiler that you are referring to a dependent type.


1 Answers

I came up with the following solution, using C++11 variadic templates and simple partial specialization:

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

It could be adapted to C++03 by using the preprocessor to generate versions for a varying number of template parameters, but there is maybe a simpler way.

like image 138
Luc Touraille Avatar answered Oct 14 '22 10:10

Luc Touraille