C++ STL类型推导

前言

以下内容根据Effective Modern C++ 条款1再结合自身理解而来(理解不对的还望指正,谢谢)
感谢作者 Scott Meyers带来这么好的书籍

类型推导不仅仅依赖 expr还依赖 ParamType

```
template<typename T>
void f(ParamType param);、
f(expr);
1. 编译期间将推导出两个类型: T, ParamType 分别对应的类型。
2. 往往两个型别不一样。因为ParamType中常含有修饰词: const, &, && 等等

template <typename T>
void f(const T& param);
1. f(1); : T int, ParamType(const T&): const int &
2. 也许你会认为 T的类型就是expr的类型,但不总成立,因为T的类型不仅仅依赖 expr, 还依赖 ParamType的形式
```

ParamType 具有指针或引用型别 (但不是万能引用&&)

  1. 如果expr具有引用型别,忽略它
  2. 然后再通过expr与ParamType的型别来确定T的型别
    1) 引用
    template <typename T>
    void f(T& param);
    ex:
    int        a = 10;       // a 的型别是 int
    const int  b = a;        // b 的型别是 const int
    const int &c = a;        // c 的型别是 const int &
    f(a);                    // ParamType型别: int &; T的型别: int
    f(b);                    // ParamType型别:const int &, T的型别: const int 
    f(c);                    // expr有引用,忽略, ParamType型别:const int &, T的型别: const int 
    :请思考以上三种调用,在void f(T& param) 定义中修改param会发生什么,如果可以的话。
    
    : 新增
    template <typename T>
    void f(const T& param);
    f(a);                    // T的型别: int; ParamType型别: int &
    f(b);                    // T的型别: int; ParamType型别: const int &
    f(c);                    // T的型别: int; ParamType型别: const int &
    : 新增 void f(const T& param); 为什么推导结果如上?(最优适配)
    
    2) 指针 (忽略之前的模板函数)
    template <typename T>
    void f(T* param);
    int         a = 10;       // 同上
    int       *px = &a;
    const int *pa = &a;
    f(&a);                    // T的型别: int; ParamType型别: int *
    f(px);                    // T的型别: int; ParamType型别: int *
    f(pa);                    // T的型别: int; ParamType型别: const int *
    

ParamType 是一个万能引用(&&) - 区分左右值!!!

  1. 若 expr 是左值, T和ParamType均被推导为左值引用(废话?)
    • 结果存在双重奇特: ① T 唯一被推导出引用的情形; ② 尽管声明时使用的是右值引用语法,但他的型别推导却是左值引用。
  2. 若 expr 是右值, 则按照指针或引用(非万能引用)的方式推导
    template <typename T>
    void f(T&& param);
    int        a = 8;        // 同前
    const int  b = a;        // 同前
    const int &c = a;        // 同前
    f(a);                    // a是==左==值 - T的型别: int &; ParamType型别: const int &
    f(b);                    // b是==左==值 - T的型别: const int &; ParamType型别: const int &
    f(c);                    // c是==左==值 - T的型别: const int &; ParamType型别: const int &
    f(8);                    // 8是==右==值 - T的型别: int; ParamType型别: int &&
    

ParamType 既非指针也非引用 - 值

该情况下意味无论传入什么,param仅仅是它的一个副本(值同,地址不同, 全新的对象)
  1. 一如之前,若expr具有引用型别,忽略引用部分
  2. 忽略引用性后, 若expr是 const 或 volatile (一般用于设备驱动)对象同样忽略
    template <typename T>
    void f(T param); 
    ex:
    int        a = 8;        // 同前
    const int  b = a;        // 同前
    const int &c = a;        // 同前
    f(a);                    // ParamType与T的型别均是: int
    f(b);                    // ParamType与T的型别均是: int
    f(c);                    // ParamType与T的型别均是: int
    :请考虑 param 的地址为什么一样?
    :const 对象的 const 指针又会怎么样?!!!!! [欢迎讨论]
    const int * const pt = &a;
    f(pt);                    // ParamType与T的型别均是: const int *
    

数组实参 - 边缘情况

  • 数组型别有别于指针类别,尽管他们有时可以互换,原因是很多语境下数组会退化成指向其首元素的指针。
  • 当一个数组传递给按值传递形参的模板时,情况如何?
    template <typename T>
    void f(T param); 
    const char name[] = "Tiany"; 
    f(name);                  // ParamType与T的型别均是: const int *
    : 1 先退化出类型 const char *, 然后再进行模板推导即
    f(const char *);
    

数组引用 - What? - 后期会继续研读并完善

尽管函数无法声明真正的的数组型别的形参,但是可以声明形参为数组的引用。
```
template <typename T>
void f(T &param); // 没错,老伙计
: 这种情况下会被推导出真正的数组型别形参,这个型别也会包含数组的长度 
```
1) 先看一个又意思的模块
```
template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
    return N;
}
constexpr: 使得返回值在编译期间就可以使用,从而声明另外一个数组时,可以指定大小与另外一个数组的相同。
    const char name[] = "Tiany";
    char aliasName[arraySize(name)]; // 候老提议使用 std::array 吧
noexcept: 帮助编译器生成更好的目标代码
```
可退化成指针之物 - 后期会继续研读并完善
  • 数组
  • 函数
  • …(如果有的话)
针对数组向指针退化的一切讨论均适用函数向函数指针的退化
template <typename T>
void f1(T param);

template <typename T>
void f2(T& param);

void func(int, double);

f1(func);           // T 和 ParamType的型别: void (*)(int, double);
f2(func);           // T 和 ParamType的型别: void (&)(int, double);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值