检查类是否是模板专业化

时间:2019-03-28 11:44:29

标签: c++

我想检查一个类是否是另一个类的模板特化。我尝试过的是:

template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};

template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};

当所有模板参数都是 type自变量时,它可以正常工作,但是当某些模板参数是 non-type自变量时,则不能正常工作。例如,它与std::vector一起使用,但不适用于std::array(因为后者接受非类型参数std::size_t)。

在编译时进行检查很重要。同样,该解决方案必须适用于任何模板,而不仅仅是矢量或数组。这意味着它可以是任意数量的类型参数和任意数量的非类型参数。例如,它应与template <class A, bool B, class C, int D, class... Args> class foo;

一起使用

1 个答案:

答案 0 :(得分:6)

C ++ 20是一个奇怪的世界。可以接受交叉检查,因为我是CTAD的初学者,并且不能完全确定我已经涵盖所有基础。

此解决方案使用SFINAE检查在所请求的类模板和神秘类型之间,类模板参数推导(CTAD)是否成功。另外执行一次is_same检查,以防止不必要的转换。

template <auto f>
struct is_specialization_of {
private:
    template <class T>
    static auto value_impl(int) -> std::is_same<T, decltype(f.template operator()<T>())>;

    template <class T>
    static auto value_impl(...) -> std::false_type;

public:
    template <class T>
    static constexpr bool value = decltype(value_impl<T>(0))::value;
};

// To replace std::declval which yields T&&
template <class T>
T declrval();

#define is_specialization_of(...) \
    is_specialization_of<[]<class T>() -> decltype(__VA_ARGS__(declrval<T>())) { }>::value

// Usage
static_assert(is_specialization_of(std::array)<std::array<int, 4>>);

First 警告:由于我们无法在不知道类参数的情况下以任何方式声明类模板的参数,因此只能通过跳过一些内容来将其传递到将执行CTAD的位置篮球。 C ++ 20 constexpr和模板友好的lambda在这里有很多帮助,但是语法很繁琐,因此是辅助宏。

第二个警告:这仅适用于可移动类型,因为CTAD仅适用于对象声明,而不适用于引用声明。也许将来的提案会允许诸如std::array &arr = t;之类的东西,然后将其解决!

实际上是通过记住C ++ 17保证了复制删除来解决的,该复制复制允许在这种情况下从不可移动的rvalue直接初始化!