如何检查类型是否是给定类模板的实例化?

Luc*_*lle 13 c++ templates template-meta-programming

是否可以检查类型是否是特定模板的实例化?

我有一个类模板,其中一个模板参数必须是特定模板的实例化,或其他类型.例如,考虑一个类型列表的简单定义:

struct null_type;

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

    typedef Head head;
    typedef Tail tail;
};
Run Code Online (Sandbox Code Playgroud)

现在,我想,以确保规定的类型Tail模板参数始终为的一个实例typelistnull_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;
};
Run Code Online (Sandbox Code Playgroud)

但是,我最终复制代码,这是我想避免的.理想情况下,我需要一个特性来测试类型是否是模板的实例化,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;
};
Run Code Online (Sandbox Code Playgroud)

这样的特征(is_instantiation_of)是否已经在标准库或Boost中可用?有可能写一个吗?

Luc*_*lle 21

我提出了以下解决方案,使用C++ 11可变参数模板和简单的部分特化:

#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 {};
Run Code Online (Sandbox Code Playgroud)

它可以通过使用预处理器为不同数量的模板参数生成版本来适应C++ 03,但可能有一种更简单的方法.

  • 顺便说一句,我打电话给[我的版本](https://bitbucket.org/martinhofernandes/wheels/src/default/include/wheels/type_traits.h%2B%2B#cl-161)`is_specialization_of`因为这是正确的术语这个."实例化"是生成"专业化"的*过程*. (5认同)
  • 请注意,解决方案barfs如果`Template`参数是一个具有非类型参数的模板,例如`template <class T,int I> struct foo {...}`(gcc 4.7) (4认同)
  • 不适用于“std::array”和所有此类模板 - 请参阅之前的评论 (2认同)