检查类型是否为模板?

时间:2021-04-16 16:24:06

标签: c++ c++20

我试图检测一个类型(或者更准确地说,一个标识符作为技术模板不是一个类型)是否是一个模板,例如有一个函数 isTemplate ,它的行为方式如下:

template <typename T>
struct X;
struct Y;
template <int N>
struct Z;

isTemplate<X>(); // Should return true
isTemplate<Y>(); // Should return false
isTemplate<Z>(); // Should return true. This one is especially tricky to get the correct results.

如何实现 isTemplate 函数?

注意:我尝试了以下简单的实现:

template <typename T> // If T is a simple type this overload will be selected
consteval bool isTemplate(int) {
   return false;
}
template <template <class...> class T> // This overload will be selected if T is a template and fits in as a template template parameter
consteval bool isTemplate(char) { // Dummy char parameter to avoid redefinition
   return true;
}

但是当它需要检测带有非类型参数的模板时它不起作用。

1 个答案:

答案 0 :(得分:4)

YSC's Answer 扩展到 another related question,您可以添加一个函数重载,该函数重载使用 auto... 非类型模板参数的参数包来检测接受非类型参数的模板。

#include <iostream>
#include <type_traits>

struct foo {};
template<typename T>  struct bar {};
template<int I>  struct baz {};

template<template<class ...> class T>
constexpr bool is_template() { return true; }

// ADDITIONAL SPECIALIZATION for non-type arguments
template<template<auto ...> class T>
constexpr bool is_template() { return true; }

template<class T>
constexpr bool is_template() { return false; }

int main() {
    std::cout << is_template<foo>() << '\n'; // 0
    std::cout << is_template<bar>() << '\n'; // 1
    std::cout << is_template<baz>() << '\n'; // 1
}

Live Demo


据我所知,目前没有办法定义一个同时接受类型和非类型模板参数的参数包。实际上,这可能意味着必须为 std::array 之类的东西编写特殊情况。