检查类是否是模板专业化 [英] Check if class is a template specialization

查看:84
本文介绍了检查类是否是模板专业化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to check if a class is a template specialization of another one. What I have tried is:

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自变量时,它工作正常是非类型参数。例如,它可以与 std :: vector 一起使用,但不能与 std :: array 一起使用(因为后者接受非类型参数 std :: size_t )。

It works fine when all template parameters are type arguments but not when some are non-type arguments. For example it works with std::vector but not std::array (since the later accepts an non-type argument std::size_t).

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

It's important that the check is made at compile time. Also the solution must work for any template, not just vectors or arrays. That means that it can be any number of type arguments and any number of non-type arguments. For example it should work with template <class A, bool B, class C, int D, class... Args> class foo;

推荐答案

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

C++20 is a weird, weird world. Cross-checking is welcome as I'm a beginner with CTAD and not entirely sure I've covered all bases.

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

This solution uses SFINAE to check whether class template argument deduction (CTAD) succeeds between the requested class template and the mystery type. An additional is_same check is performed to prevent against unwanted conversions.

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在这里有很多帮助,但是语法很繁琐,因此是辅助宏。

First caveat: Since we can't declare a parameter for the class template in any way without knowing its arguments, passing it around to where CTAD will be performed can only be done by jumping through some hoops. C++20 constexpr and template-friendly lambdas help a lot here, but the syntax is a mouthful, hence the helper macro.

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

Second caveat: this only works with movable types, as CTAD only works on object declarations, not reference declarations. Maybe a future proposal will allow things such as std::array &arr = t;, and then this will be fixed!

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

Actually fixed by remembering that C++17 has guaranteed copy-elision, which allows direct-initialization from a non-movable rvalue as is the case here!

这篇关于检查类是否是模板专业化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆