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等类型。我这里就没实现这两个了。