万能引用类型
从上一章如何查看类型推断中,我们发现经过模板的类型推导,T的类型是不完整的,我们想得到完全的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| template<typename T> void myfunc(T&& tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; }
int i = 18; const int j = i; const int& k = i; myfunc(i); myfunc(j); myfunc(k); myfunc(100);
|
传值方式
如果实参是引用类型,则引用类型会被忽略,T不会被推导为引用类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| template<typename T> void myfunc2(T tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; }
int i = 18; const int j = i; const int& k = i; myfunc2(i); myfunc2(j); myfunc2(k);
int& m = i; myfunc2(m); myfunc2<int&>(m);
|
若实参是const,则const会被忽略,T不会被推导为const类型(毕竟产生的是新副本)
1 2 3 4 5 6 7 8 9
| char mystr[] = "I Love China"; const char* const p = mystr;
myfunc2(p);
|
结论:如果传递的是const char* 或者const char[],这个const会被保留
传值方式的引申–std::ref与std::cref
当函数模板定义中使用传值方式,可以通过std::ref和std:;cref引用方式传递参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| template<typename T> void myfunc3(T tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; int& tmpvaluec = tmprv; tmpvaluec = 1200; }
int m = 180; myfunc3(std::ref(m)); cout << "m=" << m << endl;
|
数组做实参
用数组名作为实参传递,通常情况下会退化为指针
1 2 3 4 5 6 7 8 9 10 11
| template<typename T> void myfunc4(T tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; }
const char mystr[] = "l love china"; myfunc4(mystr);
|
如何得到完整的类型,一个数组,其大小都属于数组类型一部分
1 2 3 4 5 6 7 8 9 10 11
| template<typename T> void myfunc5(T& tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; }
const char mystr[] = "l love china"; myfunc5(mystr);
|
如何得到数组大小
1 2 3 4 5 6 7 8 9 10 11 12 13
| template<typename T,unsigned L1> void myfunc6(T(& tmprv)[L1]) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; cout << L1 << endl; }
const char mystr[] = "l love china";
myfunc6(mystr);
|
函数名做实参
1 2 3 4 5 6 7 8 9 10 11 12
| template<typename T> void myfunc7(T tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; }
myfunc7(testFunc);
|
初始化列表做实参
利用#include
1 2 3 4 5 6 7 8 9 10 11 12
| template<typename T> void myfunc9(std::initializer_list<T> tmprv) { cout << "-----------------begin------------------" << endl; using boost::typeindex::type_id_with_cvr; cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl; cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>().pretty_name() << endl; cout << "-------------------end----------------------" << endl; }
myfunc9({ 1,2,3 });
|
总结
推断中,引用类型实参的引用类型等于不存在
万能引用,实参为左值或者右值,推断结果不一样
按值传递的实参,传递给形参时const属性不起作用,但传递是引用则另当当别论
数组或者函数类型再类型推断中会被看做是指针,除非函数模板的形参是引用。
初始化列表不能直接推断成std::initializer_list,必须在函数模板中明确这种类型
Author:
xiao chong
Permalink:
http://example.com/2021/12/03/Type-inference2/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY?