实例代码
// 理解模板类型推断、查看类型推断结果
#include <iostream>
//#include <boost/type_index.hpp>
//template<typename T> //T是类型模板参数,所以T是右类型的
//void myfunc(T& tmprv){ //tmprv 形参,形参也是有类型的,往往tmprv形参的类型和T类型模板参数的类型不一样
// cout << "------------begin----------" << endl;
//
// using boost::typeindex::type_id_with_cvr;
// cout << "T = " << type_id_with_cvr<T>().pretty_name() << endl; //显示T 类型。
// cout << "tmprv = " << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; //显示tmprv 类型
// cout << "-------------end-----------" << endl;
//}
//template<typename T> //T是类型模板参数,所以T是右类型的
//void myfunc1(const T& tmprv){ //tmprv 形参,形参也是有类型的,往往tmprv形参的类型和T类型模板参数的类型不一样
// cout << "------------begin----------" << endl;
//
// using boost::typeindex::type_id_with_cvr;
// cout << "T = " << type_id_with_cvr<T>().pretty_name() << endl; //显示T 类型。
// cout << "tmprv = " << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; //显示tmprv 类型
// cout << "-------------end-----------" << endl;
//}
//template<typename T> //T是类型模板参数,所以T是右类型的
//void myfunc2(T* tmprv){ //tmprv 形参,形参也是有类型的,往往tmprv形参的类型和T类型模板参数的类型不一样
// cout << "------------begin----------" << endl;
//
// using boost::typeindex::type_id_with_cvr;
// cout << "T = " << type_id_with_cvr<T>().pretty_name() << endl; //显示T 类型。
// cout << "tmprv = " << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; //显示tmprv 类型
// cout << "-------------end-----------" << endl;
//}
//template<typename T> //T是类型模板参数,所以T是右类型的
//void myfunc3(T&& tmprv){ //tmprv 形参,形参也是有类型的,往往tmprv形参的类型和T类型模板参数的类型不一样
// cout << "------------begin----------" << endl;
//
// using boost::typeindex::type_id_with_cvr;
// cout << "T = " << type_id_with_cvr<T>().pretty_name() << endl; //显示T 类型。
// cout << "tmprv = " << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; //显示tmprv 类型
// cout << "-------------end-----------" << endl;
//}
//template<typename T> //T是类型模板参数,所以T是右类型的
//void myfunc4(T tmprv){ //tmprv 形参,形参也是有类型的,往往tmprv形参的类型和T类型模板参数的类型不一样
// cout << "------------begin----------" << endl;
//
// using boost::typeindex::type_id_with_cvr;
// cout << "T = " << type_id_with_cvr<T>().pretty_name() << endl; //显示T 类型。
// cout << "tmprv = " << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; //显示tmprv 类型
// cout << "-------------end-----------" << endl;
//}
int main(int argc, const char * argv[]) {
//一: 如果查看类型推断结果
//推断(推导)
// 通过“查看编译器类型推断的结果” 这个手段来让大家学习并掌握C++类型推断的规则
//二: 理解模板类型推断
// myfunc1(100);//T被推断为int , tmprv会被推断为 const int &
//2.1 指针或者引用类型
//如果tmprv类型是个指针或者引用,但不是个万能引用(T&&).
int i = 18; // int
const int j = i; // const int
const int &k = i; // const int &
myfunc(i); // 输出: T = int , tmprv = int &
myfunc(j); // 输出: T = const int, tmprv = const int &
myfunc(k); // 输出: T = const int, tmprv = const int &
//a). 若实参是引用类型, 则引用类型会被忽略掉, T不会被推导为引用类型
//b). 当我们向引用类型的形参tmprv传入const类型实参时,形参就会成为const &;
//实参的const 属性会成为类型模板参数T类型推导的组成部分,所以不用担心在myfunc中能够修改原来有const 属性的实参。
myfunc1(i); // 输出: T = int, tmprv = int const &
myfunc1(j); // 输出: T = int, tmprv = int const &
myfunc1(k); // 输出: T = int, tmprv = int const &
const int *pi = &i;
myfunc2(&i); // T = int, tmprv = int*
myfunc2(pi); // T = const int, tmprv = const int *
// 结论,如果tmprv中没有const, 则实参中的const就会被带到T类型中去。如果tmprv 中有const,则T类型中不会带const
//2.2 万能引用 : 如果tmprv类型是个万能引用:T&& ,能接受左值,也能接受右值,而且,你传递进来d左值/右值,万能引用的表现是不同的
myfunc3(i); //i是左值, T = int& , tmprv = int &
myfunc3(j); //j是左值, T = const int &, tmprv = const int &
myfunc3(k); //k是个左值, T = const int &, tmprv = const int &
myfunc3(10); //100是个右值, T = int , tmprv = int &&
//2.3 传值方式 : 如果tmprv 类型不是指针, 也不是引用,而是常规的传值方式传递
myfunc4(i); // T = int, tmprv = int
myfunc4(j); // T = int, tmprv = int, const 属性没传递进去,因为对方是新副本
myfunc4(k); // T = int, tmprv = int,const 属性没传递进去,因为对方是新副本
//现在我们传递指针进去
char mystr[] = "I Love China!";
myfunc4(mystr); // T = const char* , tmprv = const char *;
//第二个const 没有了, 第一个const 保留
//总结: 如果你传递的是const char * 或者const char[]数组, 那这个const会被保留。
//2.4 数组做实参
//2.5 函数名做实参
//总结:
//(1) 推断中,引用类型实参的引用类型等于不存在。
//(2) 万能引用,实参为左值或者右值,推断的结果不同
//(3) 按值传递的实参,传递给形参时const属性不起作用,则传递过去指针则另当别论。
//(4) 数组或者函数类型再类型推断中被看做是指针,除非函数模板的形参是个引用。
system("pause");
return 0;
}