模板类型推导 T

  1. 类型推导

    • c++98

      • 只有template一种.
    • c++11

      • auto template并做了一点改良.
    • c++14

      • c++11的基础上做了加强auto和decltype的组合.
    • 推导优劣

      • 好处

        • 少打代码.
        • 可以声明不确定类型的变量类型.
        • 必须初始化.
        • 在修改某返回类型时,不用改太多.
      • 劣势

        • 阅读性不强.
        • 甚至可能得不到预期的.
    • 地位

      • C++的新特性基本都是基于类型推导,所以需要好好的学习掌握类型推导的原理.
    • 主要内容

      • 类型推导如何实现的,怎么看类型推导出来的结果.
    • 核心

      • 都是编译器需要支持对应语法.
  2. 类型推导

    • 关系

      • template支持类型推导。
      • auto使用了template的规则进行类型推导,也有部分的差异。
      • decltype则是全新的逻辑.
    • 总纲

      • 变量本身强相关. &,*都是.
      • 变量本身不想管. 值传递.
    • 原则

      类型 规则 说明
      T& T = valuetype - argtype argtype中包含&
      T* T = valuetype - argtype argtype中包含*
      T&& T = valuetype - argtype argtype中包含&&
      T非指针 T = valuetype - argtype argtype最终的变量是*类型.
  3. T&

    • 说明

      • argtype中包含&,即左值右值和const,volatile,*,none之类的修饰进行分析.
      • 这里仅仅部分的案例.
    • 分析

      • 引用就是指针,指针则会关注指针指向的类型.
      • 即对于指针指向内容的约束,只能扩大,不能缩小.
    • 概括

      • 引用取对象的完整类型.
      • T = valuetype - argtype
    • 案例一分析

      template<typename T>
      void show(const T& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         show(1);
      }
      
      • T = valuetype - argtype = int&& - const &,利用集合运算. 则T = int.
      • 最终的argtype = const int&
      • 因为有const所以&&等价于&.
    • 案例二分析

      template<typename T>
      void show(const T& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         int a = 1;
         show(a);
      }
      
      • T = valuetype - argtype = int & - const & = int.则T = int.
      • 最终的是valuetype = const int &
    • 案例三分析

      template<typename T>
      void show(T& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         int a = 1;
         show(a);
      }
      
      • T = valuetype - argtype = int & - & = int,则T = int.
      • 最终的valuetype = int &.
    • 案例三分析

      template<typename T>
      void show(T& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(a);
      }
      
      • T = valutype - argtype = const int & - & = const int, 则T = const int
      • 最终 valuetype = const int &
    • 案例四

      template<typename T>
      void show(T&& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(&a);
      }
      
      • 这里加入了指针类型,因为指针类型和变量类型是两个独立的存在。
      • T = valuetype - argtype = const int * && - && = const int *.
    • 总结

      • 引用,不论是&,&&都可以按照这个表达式进行计算. 但是需要区分右值&&和万能引用的场景.
      • T&&是万能,其他格式都是右值引用.
  4. T*

    • 说明

      • argtype中的值传递是指针类型。
    • 指针类型和指向类型

      • 指针类型: 是指针这个变量本身的类型.有对应的修饰。
      • 指向类型: 是地址对应的变量是某个类型.
    • 概括

      • 指针取指向类型,而不是变量本身.
      • T = valtype - argtype.
      • 注意: 变量的引用和指向类型可能会有歧义.
    • 案例分析

      • 比较好理解的就是typedef int *int_ptr;
      • *int_ptr = int.
      • 同理typedef const int *c_intptr;,*c_intptr = const int.
      • 变量本身的所有的类型修饰一般在对应*之后.
      • typedef的可阅读性变差,C++11之后就变成使用using了.
    • 核心

      • T&实际就是*类型.
    • 案例一

      template<typename T>
      void show(T* a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(&a);
      }
      
      • &aconst int * &&类型.但是argtype中没有引用所以忽略&&.
      • T = valtype - argtype = const int* - * = const int
    • 案例二

      template<typename T>
      void show(T* &a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(&a);
      }
      
      • 编译错误,因为&a是右值,对变量本身有限制。
      • T*&a改成T*&&a即可.
    • 案例三

      template<typename T>
      void show(const T* a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(&a);
      }
      
      • &aconst int * &&类型.但是argtype中没有引用所以忽略&&.
      • T = valtype - argtype = const int* - const* = int.
  5. T&&

    • 说明

      • 万能引用,可以匹配任意类型.
    • 核心

      • 唯一可以推导出T是引用类型的机制.前面的T都是基本类型。
      • T =里面不存在&类型.
      • 比如上面的都是int,const int之类,没有&,万能引用可以.
    • 简要

      • 右值引用仅仅用来匹配右值,太大材小用了,毕竟右值的描述性字段很少,就基础的。
      • 用来扩展功能挺好的。
    • 概括

      • 万能引用形式像右值引用,但是也有右值匹配的功能.
      • T = valuetype - argtype.,注意,这里的& - && = &
    • 注意

      • 因为右值一般是消亡值,所以可以回收利用资源.
    • 案例一

      template<typename T>
      void show(T&& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(&a);
      }
      
      • &aconst int *&&.
      • T = valuetype - argtype = const int *&& - && = const int *.
    • 案例二

      template<typename T>
      void show(T&& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(a);
      }
      
      • a是一个const int &类型。
      • T = valuetype - argtype = const int & - && = const int &.
    • 案例三

      template<typename T>
      void show(T&& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         show(7);
      }
      
      • 7int &&类型.即普通右值.最终有int&&.
      • T = valuetype - argtype = int && - && = int.
  6. T

    • 说明

      • 就是一个值传递,形参.
    • 核心

      • 形参就是和原本的参数无关,拷贝值,可以随意操作.
    • 概要

      • 值传递,valuetype仅仅保留基础类型.
      • 不将const,volatile之类的修饰用于推测.
      • T = valuetype - valuetype - const volatile XXX
    • 案例一

      template<typename T>
      void show(T a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         show(7);
      }
      
      • T = valuetype - argtype = int.
    • 案例二

      template<typename T>
      void show(T a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int a = 1;
         show(a);
      }
      
      • T = valuetype - argtype = int.
      • 去掉了const之列的.
    • 案例三

      template<typename T>
      void show(T a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int *a = nullptr;
         show(a);
      }
      
      • a是指针,指向的类型是const int *.
      • T = argtype - valuetype = const int *
      • 本身无任何修饰.
    • 案例四

      template<typename T>
      void show(const T a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int *a = nullptr;
         show(a);
      }
      
      • 同案例三.只是对入参加了修饰.
    • 案例五

      template<typename T>
      void show(T a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int *const a = nullptr;
         show(a);
      }
      
      • 同上,这里加了a变量的类型修饰.
    • 案例六

      template<typename T>
      void show(T& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int *const a = nullptr;
         show(a);
      }
      
      • aconst int *const类型.const int *是指向的类型,后面的是const类型是自身的类型.
      • 因为这里加了T&.
      • T = valuetype - argtype = const int * const& - & = const int * const.
    • 案例七

      template<typename T>
      void show(T& a) {
                
                
         // error code
         a.nice();
      }
      int main() {
                
                
         const int *volatile a = nullptr;
         show(a);
      }
      
      • 和上面略有差异.
      • a指向类型还是const int *,但是本身是一个volatile修饰的.
      • 所以T = valutype - argtype = const int * volatile & - & = const int * volatile.
  7. 总结

    • 引用,完整类型,减法.

    • 指针,完整类型,减法.

    • 右值,完整类型,减法.

    • 万能,完整类型,减法.

    • 形参,普通类型,多减.

猜你喜欢

转载自blog.csdn.net/rubikchen/article/details/121594635
今日推荐