c++模板实参推断

//模板实参推断

//类型转换与模板类型参数

template<typename T> T fobj(T, T);//实参被拷贝

template<typename T> T fref(const T&, const T&);//引用

string s1("aaaaa");

const string s2("bbbbb");

fobj(s1, s2);//调用fobj(string,string);const被或略

fref(s1, s2);//调用ferf(const string&,const string&)将s1转换为const是允许的

int a[10], b[23];

fobj(a, b);//调用fobj(int*, int*)

fref(a, b);//错误 数组类型不匹配,如果形参是一个引用,数组不会传换成指针。

 

//使用相同模板参数类型的函数形参

//一个模板类型参数可以用作多个函数形参的类型

//由于只允许有限的几种类型转换,因此传递参数时必须具有相同的类型,否则推断的类型不匹配。

//可以将函数模板定义为两个类型参数

template<typename A, typename B>

int flexibleCompare(const A& v1, const B& v2)

{

if (v1 < v2)return -1;

if (v2 < v1)return 1;

return 0;

}

 

//正常类型转换应用于普通函数实参

//函数模板可以用普通类型定义的参数,这种函数不进行特殊处理,正常转化为对应的类型

//当调用print时,传递给它的实参会进行正常的类型转换

template<typename T> ostream &print(ostream &os, const T &obj)

{

return os << obj;

}

print(cout, 23);//实例化print(ostream&, int)

ofstream f("asdas");

print(f, 2);//使用print(ostream&, int);将f 装换为ostream&

 

//函数模板显式实参

//指定显式模板实参

template<typename T1, typename T2, typename T3>

T1 sum(T2, t3);

int i; long lng;

//T1是显式指定的,T2和T3是从函数实参类型推断而来的

//显示模板实参按由左至右的顺序与对应的模板参数匹配

auto val3 = sum<long, long>(i, lng);//long long sun(int,long)

 

//正常类型转换应用于显示指定的实参

//对于模板类型参数已经显示指定了的函数实参,也可以进行正常的类型转换

long lng;

//以下为模板函数compare(const T &v1,const T &v2)的调用

compare(lng, 1024);//错误 模板参数不匹配

compare<long>(lng, 1024);//正确 实例化compare(long,long)

compare<int>(lng, 1024);//正确 实例化compare(int,int)

 

//尾置返回类型与类型转换

//可以使用decltype来获取表达式的类型

template<typename It>

auto fcn(It beg, It end)->decltype(*beg)

{

return *beg;

}

 

//进行类型转换的标准库模板类

//为了使用模板参数的成员,必须typename

template<typename It>

auto fcn2(It beg, It end)->typename remove_reference<decltype(*beg)>::type

{

return *beg;

}

 

//函数指针和实参推断

template<typename T> int compare(const T&, const T&);

int(*pf1)(const int&, const int&) = compare;

void func(int(*)(const string&, const string&));

void func(int(*)(const int&, const int&));

func(compare);//错误 不知道使用的是那个func版本

func(compare<int>);//正确 显示的指出了使用的版本,传递了compare(const int&, const int&)

 

//模板实参推断和引用

//从左值引用函数参数推断类型

template<typename T> void f1(T&);//实参必须是一个左值

f1(i);//i是一个int,模板参数类型T是int

f1(ci);//ci是一个const int,T是const int

f1(5);//错误 传递给一个&参数的实参必须是一个左值

 

template<typename T> void f2(const T&);//可以接受一个右值

//f2中的参数是const&,实参中的const是无关的

f2(i);//i是一个int;模板参数T是int

f2(ci);//ci是一个const int,但模板参数T是int

f2(5);//一个const&参数可以绑定到一个右值,T是int

 

//从右值引用函数参数推断类型

template<typename T>void f3(T&&);

f3(4);//实参是一个int类型的右值;模板参数T是int

 

//引用折叠和右值引用参数

//引用折叠只能应用于间接创建的引用的引用,如类型别名或模板参数

//如果一个函数参数是一个指向模板类型参数的右值引用(如T&&)则它可以被当定到一个左值

//如果实参是一个左值,则推断出的模板实参类型将是一个左值引用,且函数参数将被实例化为一个左值引用参数

f3(i);//实参是一个左值,模板参数T是int&

f3(ci);//实参是一个左值,模板参数T是const int&

template<typename T>

void f3(T&& val)

{

T t = val;

t = fcn(t);

if (val == t) {/**/}//若T是引用类型,则一直为true

}

 

//std::move的定义

template<typename T>

typename remove_reference<T>::type&& move(T&& t)

{

return static_cast<typename remove_reference<T>::type&&>(t);

}

 

//转发

//某些函数需要将其一个或多个实参连同类型不变地转发给其他函数

template<typename F, typename T1, typename T2>

void flip1(F f, T1 t1, T2 t2)

{

f(t2, t1);

}

void f(int v1, int &v2)

{/**/}

f(2, i);

flip1(f, j, 4);

 

//使用std::forward保持类型信息

template<typename F, typename T1, typename T2>

void flip(F f, T1 &&t1, T2 &&t2)

{

f(std::forward<T2>(t2), std::forward<T1>(t1));

}

void g(int &&i, int &j)

{/**/}

flip(g, i, 3);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值