键入特征以识别从 CRTP class 派生的 classes

Type trait to identify classes derived from a CRTP class

我希望实现函数 is_type_of_v,能够识别类型 Skill 的模板化实例。请查看下面源代码中的主要功能,以充分理解请求。用文字比用代码更难解释。

该解决方案应适用于 c++17 下的 VS 2017。下一个 link 包含示例:https://godbolt.org/z/4x3xoh1Pb

#include <iostream>
#include <type_traits>

template<class T>
struct Base
{
private:
    constexpr Base() = default;
    friend T;
};

struct Derived1 : Base<Derived1>
{
};

struct Derived2 : Base<Derived2>
{
};

template<class T, class F, int... Ints>
struct Skill : T
{

};

int main()
{
    Skill<Derived1, std::equal_to<int>, 1, 2> object1;
    Skill<Derived2, std::equal_to<int>, 3> object2;
    Derived1 other;

    constexpr auto res1 = is_type_of_v<Skill, decltype(object1)>;//Must be true
    constexpr auto res2 = is_type_of_v<Skill, decltype(object2)>;//Must be true
    constexpr auto res3 = is_type_of_v<Skill, decltype(other)>;//Must be false
}

对于Skill,你可以写成

template <template <typename, typename, auto...> class, typename>
struct is_type_of : public std::false_type
{};

template <template <typename, typename, auto...> class C,
          typename T1, typename T2, auto ... Is>
struct is_type_of<C, C<T1, T2, Is...>> : public std::true_type
{};

template <template <typename, typename, auto...> class C, typename T>
constexpr auto is_type_of_v = is_type_of<C, T>::value;

所以你可以验证

static_assert( true  == is_type_of_v<Skill, decltype(object1)> );
static_assert( true  == is_type_of_v<Skill, decltype(object2)> );
static_assert( false == is_type_of_v<Skill, decltype(other)> );

不幸的是,此解决方案仅适用于 template-template 参数,之前接收几个类型名称,之后接收可变值列表。

我认为不可能(C++17 和 C++20)第一个位置的通用 template-template 参数的通用解决方案。

而在 C++17 之前(C++11 和 C++14)更糟,因为你不能使用 auto... 作为值。