示例详解----C++类型推导

<<示例详解—-C++类型推导>>

转载请注明出处: https://blog.csdn.net/WOW542621126/article/details/80474681

暂且只讲函数模板和auto的类型推导,decltype的类型推导略过不谈;
内容不多,直接开始:

1.函数模板类型推导

如下是一个简单的函数模板及调用方式;

template<typename T>
void func(ParamType param)
{
}

int main()
{
    int expr = 100;
    func(expr);
}

函数模板类型推导规则:

对于函数模板,T的类型推导,不仅依赖实参expr的类型,还依赖形参ParamType的类型, 具体分三种情形:

  • 1.形参类型ParamType具有指针或引用类型,但不是universal引用;

    推导规则:

    若实参expr具有引用类型,先将引用部分忽略;
    然后,对实参expr和形参ParamType类型执行模式匹配,决定T的类型;

  • 2.形参类型ParamType是一个universal引用;

    推导规则:

    如果expr是个左值,T和ParamType都会被推导为左值引用;
    如果expr是个右值,则应用常规规则(同情形1);

  • 3.形参类型ParamType既非指针也非引用;

    推导规则:

    若expr具有引用类型,则忽略其引用部分;
    忽略引用性之后,若expr是个const对象或volatile对象,也忽略之;

示例–情形1

  • 模板形参类型:T&

/** 1.形参类型ParamType具有指针或引用类型,但不是universal引用;
    推导规则:
    若实参expr具有引用类型,先将引用部分忽略;
    然后,对实参expr和形参ParamType类型执行模式匹配,决定T的类型;
*/

#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;

template<typename T>
void func1(T& param)
{
    MK_PRINT_MSG("T is : %s", type_id_with_cvr<T>().pretty_name().c_str());
}

TEST(ut_deduction, func1)
{
    int x = 11;
    const int cx = x;
    const int& rx = x;


    func1(x);   //实参类型为int,        T类型推导为int,       形参类型int&
    func1(cx);  //实参类型为const int,  T类型推导为const int, 形参类型const int&
    func1(rx);  //实参类型为const int&, T类型推导为const int, 形参类型const int&
}

执行结果:
这里写图片描述

  • 模板形参类型:const T&
template<typename T>
void func2(const T& param)
{
    MK_PRINT_MSG("T is : %s", type_id_with_cvr<T>().pretty_name().c_str());
}

TEST(ut_deduction, func2)
{
    int x = 11;
    const int cx = x;
    const int& rx = x;


    func2(x);   //实参类型为int,        T类型推导为int, 形参类型const int&
    func2(cx);  //实参类型为const int,  T类型推导为int, 形参类型const int&
    func2(rx);  //实参类型为const int&, T类型推导为int, 形参类型const int&
}

执行结果:
这里写图片描述

示例–情形2:

/** 2.形参类型ParamType是一个universal引用;
    推导规则:
    如果expr是个左值,T和ParamType都会被推导为左值引用;
    如果expr是个右值,则应用常规规则(同情形1);
*/

template<typename T>
void func3(T&& param)
{
    MK_PRINT_MSG("T is : %s", type_id_with_cvr<T>().pretty_name().c_str());
}

TEST(ut_deduction, func3)
{
    int x = 11;
    const int cx = x;
    const int& rx = x;


    func3(x);   //实参x是左值,       T类型推导为int&, 形参类型int&
    func3(cx);  //实参cx是左值,      T类型推导为const int&, 形参类型const int&
    func3(rx);  //实参rx是左值,      T类型推导为const int&, 形参类型const int&
    func3(11);  //实参11是右值,      T类型推导为int,        形参类型int&&
}

执行结果:
这里写图片描述

示例–情形3:

/** 3.形参类型ParamType既非指针也非引用(按值传递);
    推导规则:
    若expr具有引用类型,则忽略其引用部分;
    忽略引用性之后,若expr是个const对象或volatile对象,也忽略之;
*/

template<typename T>
void func4(T param)
{
    MK_PRINT_MSG("T is : %s", type_id_with_cvr<T>().pretty_name().c_str());
}

TEST(ut_deduction, func4)
{
    int x = 11;
    const int cx = x;
    const int& rx = x;

    func4(x);   //T类型推导为int, 形参类型int
    func4(cx);  //T类型推导为int, 形参类型int
    func4(rx);  //T类型推导为int, 形参类型int
    func4(11);  //T类型推导为int, 形参类型int
}

执行结果:
这里写图片描述

2.auto类型推导

auto类型推导规则:

对于auto变量声明, auto的类型推导,与函数模版推导类似, 也分为三种情况:
1.变量类型是指针或者引用,但不是universal引用;
2.变量类型是universal引用;
3.变量类型既非指针也非引用;

但是有一个特例,当用于auto声明变量的表达式是用大括号{}时,推导的类型是std::initializer_list<>;

示例–情形1:

TEST(ut_deduction, func5)
{
    int x =11;

    const auto& rx1 = x;//情况1,auto推导为int,所声明的变量类型为const int&
    MK_PRINT_MSG("type of rx1 is : %s", type_id_with_cvr<decltype(rx1)>().pretty_name().c_str());


    auto& rx2 = rx;//情况1,auto推导为const int,所声明的变量类型为const int&
    MK_PRINT_MSG("type of rx2 is : %s", type_id_with_cvr<decltype(rx2)>().pretty_name().c_str());
}

执行结果:
这里写图片描述

示例–情形2:

TEST(ut_deduction, func6)
{
    int x = 11;
    const int cx = x;

    auto&& ur1 = x; //情况2,auto推导为int&,所声明的变量类型为int&
    MK_PRINT_MSG("type of ur1 is : %s", type_id_with_cvr<decltype(ur1)>().pretty_name().c_str());


    auto&& ur2 = cx;//情况2,auto推导为const int&,所声明的变量类型为 const int&
    MK_PRINT_MSG("type of ur2 is : %s", type_id_with_cvr<decltype(ur2)>().pretty_name().c_str());


    auto&& ur3 = 11;//情况2,auto推导为int,,所声明的变量类型为int&&
    MK_PRINT_MSG("type of ur3 is : %s", type_id_with_cvr<decltype(ur3)>().pretty_name().c_str());
}

执行结果:
这里写图片描述

示例–情形3:

TEST(ut_deduction, func7)
{
    auto x = 11;        //情况3,auto推导为int,所声明的变量类型为int
    MK_PRINT_MSG("type of x is : %s", type_id_with_cvr<decltype(x)>().pretty_name().c_str());

    const auto cx = x;//情况3,auto推导为int,所声明的变量类型为const int
    MK_PRINT_MSG("type of cx is : %s", type_id_with_cvr<decltype(cx)>().pretty_name().c_str());
}

执行结果:
这里写图片描述

示例–特例:

当用于auto声明变量的表达式是用大括号{}时,推导的类型是std::initializer_list<>;

TEST(ut_deduction, func8)
{
    auto v1 = 11;
    MK_PRINT_MSG("type of v1 is : %s", type_id_with_cvr<decltype(v1)>().pretty_name().c_str());//int

    auto v2(11);
    MK_PRINT_MSG("type of v2 is : %s", type_id_with_cvr<decltype(v2)>().pretty_name().c_str());//int

    auto v3 = {11};
    //std::initializer_list<int> 
    MK_PRINT_MSG("type of v3 is : %s", type_id_with_cvr<decltype(v3)>().pretty_name().c_str());

    auto v4{11};
    //vs2015执行结果是int,gcc结果是std::initializer_list<int> 
    MK_PRINT_MSG("type of v4 is : %s", type_id_with_cvr<decltype(v4)>().pretty_name().c_str());
}

执行结果:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值