如何检查非模板类和模板类之间的类型相等性?

Lun*_*ape 3 c++ templates typechecking specialization type-traits

假设我有

class A {};

template<typename T, typename U> class Wrapper {};
Run Code Online (Sandbox Code Playgroud)

我正在尝试检查包装器的第一个内部类型是否为A.

typeCheck(new A(), new Wrapper<A,B>);  // expect true
typeCheck(new A(), new Wrapper<C,B>);  // expect false
Run Code Online (Sandbox Code Playgroud)

最好的方法是什么?


我尝试过模板部分专业化,但没有运气。

这是我尝试过的代码:

template<typename T> struct get_inner {
  using type = T;
}

template<typename T, typename U>
struct get_inner<Wrapper<T,U>> {
  using type = T;
}

std::cout<< typeid(get_inner<decltype(new Wrapper<A,B>)>::type);
Run Code Online (Sandbox Code Playgroud)

控制台显示相同的包装类型而不是内部类型A。这里有什么错误吗?

JeJ*_*eJo 5

控制台显示相同的包装类型而不是内部类型A。这里有什么错误吗?

的类型new Wrapper<A,B>是指向 的指针Wrapper<A,B>,而不是Wrapper其本身。因此,它不适合您的专业化,并选择了第一个基本模板,其中type等于传递的类型,即Wrapper<A,B>*.

相反,你应该写

typename get_inner<Wrapper<A,B>>::type; 
Run Code Online (Sandbox Code Playgroud)

请注意,这decltype也是不必要的,因为您已经传递了模板类型本身。

由于您试图在编译时检查类型,因此我建议std::is_same也使用。例如

std::cout << std::boolalpha
          << std::is_same_v<typename get_inner<Wrapper<A,B>>::type, A>;
Run Code Online (Sandbox Code Playgroud)

查看演示


最好的方法是什么?

嗯,方法有很多!

一种方法是,std::is_same_v在标准类型特征中,您可以直接为此编写特征:

#include <type_traits>  // std::false_type, std::true_type

template<typename T> // base template
struct is_inner_type : std::false_type{};

template<typename T, typename U> // specialization
struct is_inner_type<Wrapper<T,U>> {
  static constexpr bool value = std::is_same_v<A, T>;
};
// variable template for convenience
template<typename ClassType>
inline constexpr bool is_inner_type_v = is_inner_type<ClassType>::value;
Run Code Online (Sandbox Code Playgroud)

你会像这样使用它

static_assert(!is_inner_type_v<Wrapper<int, float>>);
static_assert(is_inner_type_v<Wrapper<A, float>>);
Run Code Online (Sandbox Code Playgroud)

查看演示

但是,这还不够通用,不足以更改要检查的类型。在那里,我会建议类似于您最初的实现的东西。

// traits for finding the T & U type!
template <typename T> struct Class;
template <template<typename A, typename B> class Type,  typename A, typename B>
struct Class<Type<A,B>> {
    using T = A;
    // using U = B; // if needed
};
template <typename Type> using  class_t = typename Class<Type>::T;
// template <typename Type> using  class_u = typename Class<Type>::U; // if needed

// variable template for convenience
template<typename ClassType, typename TypeToCheck>
inline constexpr bool is_inner_type_v = std::is_same_v<class_t<ClassType>, TypeToCheck>;
Run Code Online (Sandbox Code Playgroud)

我使用了模板模板类专业化,以防您想让它更通用并将其用于其他类似的类模板。