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。这里有什么错误吗?
控制台显示相同的包装类型而不是内部类型
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)
我使用了模板模板类专业化,以防您想让它更通用并将其用于其他类似的类模板。