1.类型萃取的原理
类型萃取利用模板形参的推演方式使得类型去掉了引用性质:
cpp
//消除引用,保留原始特性 //类型萃取
/// </summary>
/// <param name="it"></param>
template<class _Ty>
struct my_remove_reference
{
my_remove_reference()
{
int x = 10;
_Ty Y = 10;
}
};
template<class _Ty>
struct my_remove_reference<_Ty&>
{
my_remove_reference()
{
int x = 10;
_Ty Y = 10;
}
};
template<class _Ty>
struct my_remove_reference<_Ty&&>
{
my_remove_reference()
{
int x = 10;
_Ty Y = 10;
}
};
int main()
{
my_remove_reference<int>i;
my_remove_reference<int&>ilr;
my_remove_reference<const int&>cilr;//调用struct my_remove_reference<_Ty&>
my_remove_reference<int&&>rll; //调用struct my_remove_reference<_Ty&&>
//student<int&> s1;
// cout << s1.X << endl;
}
#endif
使用示例1:acs作为了a的引用。
cpp
/*类型转化示例,头文件type_traits*/
//1 转换成引用型别
int main()
{
int a = 10;
int& b = a;
add_lvalue_reference<int>::type acs = a;
acs = 100;
cout << a;
}
使用示例2:rm的类型是int 而非int&
cpp
2 将引用转化为值类型
int main()
{
int a = 10;
int& ab = a;
remove_reference<int&>::type rm = ab;
std::cout<<typeid(rm).name();
return 0;
}
2.在模板函数中,编译器无法确认返回类型,需要使用typename 告知其是类型
使用类的类型成员:为了知道模板函数中名字是否可以表示一个类型,用typename通知这是表示一个类型。
cpp
#if 0
/*使用类的类型成员:为了知道模板函数中名字是否可以表示一个类型,用typename通知这是表示一个类型*/
//此为返回一个容器成员类型的函数
template<class T>
typename T::value_type fun(const T& x)
{
cout << "T" << typeid(T).name() << "\n";
cout <<"typeid(T::value_type).name()"<< typeid(T::value_type).name() << "\n";
if (!x.empty())
{
return x.back();
}
else {
return typename T::value_type();
}
//std::cout << x << " , T::value_type :" << typeid(T).name() << "\n";
//return typename T:: value_type();
}
int main()
{
int a = 10;
vector<int> vec;
auto res1 = fun<vector<int>>(vec);
cout << typeid(res1).name() << "\n";
cout << res1;
return 0;
}
#endif
T::value_type 表示为容器元素的类型。
注意:auto res1 = fun<vector<int>>(vec); 也可写成auto res1 = fun(vec);
一个是显示指定参数类型,一个是隐式的自动匹配对应的模板函数。
3.使用decltype关键字返回你想要返回的类型
在某些时候我们不想使用指定模板实参作为函数的返回值,而使用此关键字告诉编译器,返回类型和decltype括号中的类型相同。
示例:
cpp
template<class It>
auto fnc1(It beg, It end) ->decltype(*beg)
{
return *beg;
}
int main()
{
string st = "111";
vector<string>arr={ "111" };
auto &res = fnc1(arr.begin(), arr.end());
cout << typeid(res).name() << " ";
cout << res;
return 0;
}
移除引用型别
cpp
template<class It>
auto fnc(It beg, It end) ->//decltype(*beg)
typename remove_reference<decltype(*beg)> ::type
{
cout<<typeid(*beg).name()<<" ";
//*beg = 100;
return *beg;
}
int main()
{
string st = "111";
vector<string>arr={ "111" };
auto res = fnc(arr.begin(), arr.end());
cout << typeid(res).name() << " ";
cout << res;
return 0;
}
注意,此函数调用时的返回类型要求是非引用类型,所以在函数中做了移除引用型别的处理。
4.引用折叠和理解move
5.模板参数与作用域
6.类模板的成员模板
7,显示实例化