std::traits学习
类型判断和退化(获取原始类型)的原理就是利用模板的特例化。根据调用模板的特例化,在特例化模板中实现判断的逻辑或者退化的逻辑。
一、类型判断
判断整型数据的模板类
#include <iostream> namespace zk {template<typename T, T Val>struct integral_constant {static constexpr T value = Val;};using false_type = integral_constant<bool, false>;using true_type = integral_constant<bool, true>;template<typename T>struct isInteger :false_type {};template<>struct isInteger<std::int8_t> :true_type {};template<>struct isInteger<std::int16_t> :true_type {};template<>struct isInteger<std::int32_t> :true_type {};template<>struct isInteger<std::int64_t> :true_type {};template<>struct isInteger<std::uint8_t> :true_type {};template<>struct isInteger<std::uint16_t> :true_type {};template<>struct isInteger<std::uint32_t> :true_type {};template<>struct isInteger<std::uint64_t> :true_type {};template<typename T>constexpr bool is_integer_v = isInteger<T>::value;
}int main() {if (zk::is_integer_v<std::string>) {std::cout << "is integer" << std::endl;}else {std::cout << "not integer" << std::endl;}if (zk::is_integer_v<std::int32_t>) {std::cout << "is integer" << std::endl;}if (zk::is_integer_v<std::uint32_t>) {std::cout << "is integer" << std::endl;}if (zk::is_integer_v<std::int64_t>) {std::cout << "is integer" << std::endl;}return 0;
}
其中
template<typename T, T Val>
struct integral_constant {static constexpr T value = Val;
};
申明定义了一个模板类,存放了一个由模板参数决定的静态常量成员变量。然后用这个模板类,申明并定义了false_type和true_type
using false_type = bool_constrait<bool, false>;
using true_type = bool_constrait<bool, true>;
然后定义一个模板类,默认匹配到模板类时,不是int整型
template<typename T>struct isInteger :false_type {};
当匹配到特例化类时,是int整型
template<>struct isInteger<std::int8_t> :true_type {};template<>struct isInteger<std::int16_t> :true_type {};template<>struct isInteger<std::int32_t> :true_type {};template<>struct isInteger<std::int64_t> :true_type {};template<>struct isInteger<std::uint8_t> :true_type {};template<>struct isInteger<std::uint16_t> :true_type {};template<>struct isInteger<std::uint32_t> :true_type {};template<>struct isInteger<std::uint64_t> :true_type {};
没写完,还有short、long、longlong等类型
二、退化(获取原始类型)
有时需要获取到一个对象的原始类型,不含指针、不含引用、不含右值引用等
#include <iostream> namespace zk {template<typename T>struct decay {using type = T;};template<typename T>struct decay<T&> {using type = T;};template<typename T>struct decay<T&&> {using type = T;};template<typename T>struct decay<T*> {using type = T;};template<typename T>struct decay<std::shared_ptr<T>> {using type = T;};template<typename T>using decay_t = typename decay<T>::type;
}int main() {std::cout << "type : " << typeid(zk::decay_t<int>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<int*>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<std::shared_ptr<int>>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<std::int32_t>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<std::int32_t*>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<std::shared_ptr<std::int32_t>>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<std::string>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<char*>).name() << std::endl;std::cout << "type : " << typeid(zk::decay_t<float*>).name() << std::endl;zk::decay_t<char*> a = 97;std::cout << "a : " << a << std::endl;return 0;
}
只移除了指针、引用和右值引用和共享指针。std::traits还可以还原出std::function、std::string等类型。我这里就没实现这两个了。