检查类是否是模板专业化

use*_*019 8 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 {};
Run Code Online (Sandbox Code Playgroud)

当所有模板参数都是类型实参,但不是某些非类型实参时,它可以正常工作。例如,它可以使用std::vector但不能使用std::array(因为后者接受一个非类型参数std::size_t)。

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

Que*_*tin 8

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

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

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

通过记住C ++ 17保证了复制删除,实际上可以解决问题,这种复制复制允许从不可移动的rvalue直接初始化,就像这里一样!

  • 我会推断出你的模板参数。(我喜欢这个解决方案) (2认同)