当我们在编写模板函数的时候,如果用户用显示模板实参表示返回类型是最好的
但是如果用户用的是泛型的话,会给用户增加额外负担
比如我们定义一个模板,传入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