如何查看类型推断2

万能引用类型

从上一章如何查看类型推断中,我们发现经过模板的类型推导,T的类型是不完整的,我们想得到完全的类型

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;         //i的类型是int
const int j = i;    //j的类型是const int
const int& k = i;   //k的类型是const int&
myfunc(i);          //T=int& ,tmprv=int&
myfunc(j);          //T= int const&,tmprv =int const &
myfunc(k);          //T=int const & tmprv=int const &
myfunc(100);        //T=int tmprv=int&&

传值方式

如果实参是引用类型,则引用类型会被忽略,T不会被推导为引用类型

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;        //i的类型是int
const int j = i;    //j的类型是const int
const int& k = i;   //k的类型是const int&
myfunc2(i);         //T=int tmprv=int
myfunc2(j);         //T=int tmprv=int
myfunc2(k);         //T=int tmprv=int

//如果实参是引用类型,则引用类型会被忽略,T不会被推导为引用类型,除非手工引用类型(不建议这样写)
int& m = i;
myfunc2(m);
myfunc2<int&>(m);

若实参是const,则const会被忽略,T不会被推导为const类型(毕竟产生的是新副本)

char mystr[] = "I Love China";
const char* const p = mystr;
//第一个const表示p指向的目标中的内容不能通过p改变
//第二个const表示p指向一个内容后,p不可再指向其他的内容(p不可以指向不同内容)

myfunc2(p);//T=char const *,tmprv=char const*

//这表示进入到函数模板内部后,tmprv指向的内容不能通过tmprv改变,但是tmprv可以指向其他内存地址
//也就是tmprv(p)的常量性被忽略了,二tmprv(p)所指向的内容的常量性会被保留

结论:如果传递的是const char* 或者const char[],这个const会被保留


传值方式的引申–std::ref与std::cref

当函数模板定义中使用传值方式,可以通过std::ref和std:;cref引用方式传递参数

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));//std::ref和std::cref像对象包装器,编译器通过创建一个class std::reference_wrapper<T>类型的对象
cout << "m=" << m << endl;  //m=1800

数组做实参

用数组名作为实参传递,通常情况下会退化为指针

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);     //T=char const* tmprv=char const*

如何得到完整的类型,一个数组,其大小都属于数组类型一部分

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); //T = char const [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;//13
}

const char mystr[] = "l love china";
//tmprv = char const (&)[13]    --(&)代表数组的一个引用
myfunc6(mystr);

函数名做实参

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);
//T = void __cdecl(void)
//tmprv = void(__cdecl&)(void)--tmprv是一个函数引用类型

初始化列表做实参

利用#include<initializer_list>

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 });
//T = int
//tmprv = class std::initializer_list<int>

总结

  1. 推断中,引用类型实参的引用类型等于不存在

  2. 万能引用,实参为左值或者右值,推断结果不一样

  3. 按值传递的实参,传递给形参时const属性不起作用,但传递是引用则另当当别论

  4. 数组或者函数类型再类型推断中会被看做是指针,除非函数模板的形参是引用。

  5. 初始化列表不能直接推断成std::initializer_list,必须在函数模板中明确这种类型


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值