Type Trait 其实是一种概念 , 他的思想与Java 中的泛型的思想非常的相似, 他在C++中主要的用法是使用 template 可以在编译阶段根据一个或者多个 template 产出一个 type 或者 value , 在上一篇文章中讲到的 decltype , typeid ,conditional 其实都可以看做是 Type Trait 的概念
既然他只是一种概念那么为什么还要单独将他拿出来说呢,这就要感叹 C++ 标准库的厉害之处了,他为我们定义了一套非常全面的判断类型的方法
下面简单的放一下例子
#include <iostream>
#include <string>
#include <typeinfo>
#include <type_traits>
using namespace std;
template<class T>
void foo(T &t) {
// 如果是一个指针
if (std::is_pointer<T>::value) {
cout << "传入的是一个指针" << endl;
} else if (std::is_integral<T>::value) {
cout << "传入的是一个 int 数据" << endl;
} else
cout << "传入的是一个 其他 数据" << endl;
}
int main() {
char *str = "111111";
foo(str);
int num = 1;
foo(num);
foo("tsm");
return 0;
}
我们写了一个foo 的方法,这个方法传入的类型是一个模板 template 的引用 , 那么在调用过程中任何对象都是可以调用的,可以根据调用的类型来执行相对应的操作
结果:
D:\CWorkSpace\tsmTest\cmake-build-debug\tsmTest.exe
tsm 实际的类型是f
传入的是一个指针
传入的是一个 int 数据
传入的是一个 其他 数据
Process finished with exit code 0
这个里面 std::is_pointer 得到的是 std::true_type 或者 std::false_type, 而 std::is_pointer::value 得到的 true 或者 false ,那么可以不可以将这个 foo 方法修改一下呢
template<class T>
void fooImpl1(T &t){
cout << "打印 T 的值是:"<< (std::is_pointer<T>::value ? *t : t)<<endl;
}
在这个方法中,如果这个 T 是指针类型,那么就使用 *t 获取他的值,如果他不是,则直接打印他,
尝试了一下这种情况下是不被允许的,原因是 如果 val 是一个值,那么 * val 就是一个无效的数据,那么该如何修改呢,方法如下
#include <iostream>
#include <string>
#include <typeinfo>
#include <type_traits>
using namespace std;
template<class T>
void fooImpl1(T& t,std::true_type){
cout<< "是指针 取值" << *t<< endl;
}
template<class T>
void fooImpl1(T& t,std::false_type){
cout<< "不是指针 直接使用值" << t<< endl;
}
template<class T>
void fooImpl1(T& t){
fooImpl1(t,std::is_pointer<T>());
}
int main() {
char *str = "Tsm";
fooImpl1(str);
return 0;
}
结果:
D:\CWorkSpace\tsmTest\cmake-build-debug\tsmTest.exe
是指针 取值T
Process finished with exit code 0
C++标准库为我们准备了非常多的类型判断,
下面是针对类型的判断
下面是针对class 的判断
还有类关系检验
这么多都记住看来需要一段时间了,不过了解了这些信息,对于今后在源码部分的阅读会非常有帮助的,我的学习资料来自于 C++ 标准库 简体中文 第二版.pdf 提取码: ekr7 ,感兴趣的同学可以下载下来研究一下