场景
当我们在编写模板函数的时候,如果用户用显示模板实参表示返回类型是最好的
但是如果用户用的是泛型的话,会给用户增加额外负担
比如我们定义一个模板,传入vector<int>
的迭代器,要求返回他所指向的值
尾置返回类型
我们可以用decltype
来获取表达式的类型
template <typename It>
auto fcn2(It beg) -> decltype(*beg)
{
return *beg;
}
这里的decltype
为解引用运算符的左值,因此推断的类型是int&
和我们预期的int
不符(而且因为是引用,用typeid也没法查)
引用类型去除
如果我们想要的是一个int
值,那我们在定义类型的时候需要去掉这个引用
标准库提供了类型转换模板,可以用remove_reference
去除引用
template <typename It>
auto fcn(It beg) -> typename remove_reference<decltype(*beg)>::type //type是该函数返回值的成员
{
return *beg;
}
这样就可以将类型脱去引用了
测试代码
template <typename It>
auto fcn(It beg) -> typename remove_reference<decltype(*beg)>::type
{
return *beg;
}
template <typename It>
auto fcn2(It beg) -> decltype(*beg)
{
return *beg;
}
int main()
{
vector<long> a = { 123, 11 };
cout << &a[0] << endl; //和下面的fcn2作对比
cout << typeid(fcn2(a.begin())).name() << endl; //在vs里,鼠标移到fcn2上会显示他返回结果是long&
cout << fcn2(a.begin()) << endl;
cout << &fcn2(a.begin()) << endl; //这里是为了证明他是引用,所以输出地址
cout << typeid(fcn(a.begin())).name() << endl; //在vs里,鼠标移到fcn上会显示他返回结果是long
cout << fcn(a.begin()) << endl;
//cout << &fcn(a.begin()) << endl; //这里编辑器直接报错,因为他不是左值
auto pp = fcn(a.begin());
cout << &pp << endl;
}
测试结果:
0123EC30
long
123
0123EC30
long
123
00B9FA04
其他模板方法
func_name<T> | T | func_name |
---|---|---|
remove_reference | X& or X&& | X |
else | T | |
add_const | X& or const X or 函数 | T |
else | const T | |
add_lvalue_reference | X& | T |
X&& | X& | |
else | T& | |
add_rvalue_reference | X& or X&& | T |
else | T&& | |
remove_pointer | X* | X |
else | T | |
add_pointer | X& or X&& | X* |
else | T* | |
make_signed | unsigned X | X |
else | T | |
make_unsigned | signed X | unsigned X |
else | T | |
remove_extent | X[n] | X |
else | T | |
remove_all_extents | X[n1][n2] | X |
else | T |
其他说明
上面提到的typeid,是一个输出变量类型的方法
#include <typeinfo>
int a = 1;
char b = 'b';
int& c = a;
typeid(a).name(); //int
typeid(b).name(); //char
typeid(c).name(); //int