C++ primer 第五版个人笔记 第十六章 模板与泛型编程

16.1 定义模板

  1. 模板定义以关键字template开始,后跟一个模板参数列表,以逗号分隔,可以传一个或多个模板参数(T1,T2),模板参数列表不能为空;
  2. 编译器用推断出的模板参数来生成一个版本的函数叫做实例化,生成的版本叫做模板的实例;
  3. 模板类型参数前面必须使用关键字class或typename,在同一个模板参数列表中两个关键字可以混合使用,没有什么不同;
  4. 非类型模板参数的模板实参必须是常量表达式;
  5. inline或constexpr的函数模板中,inline和constexpr关键字说明符放在模板参数列表之后,返回类型之前
    template inline
    T min(const T& t1, const T &T2)
    {/* */}

     

  6. 泛型编码的两个重要原则:a模板中的函数参数是const的引用,b函数体中尽量减少对实参类型的要求;

  7.  函数模板和类模板成员函数的定义通常放在头文件中;而非模板类或模板函数不必给出定义,因此类定义和函数声明放在头文件中,普通函数和类的成员函数的定义放在源文件中,与函数模板和类模板成员函数不同; 

  8. 类模板的成员函数本身是一个普通函数,但是,类模板的每个实例都有其自己版本的成员函数,因此定义在类模板之外的成员函数就必须以关键字template开始,后接类模板参数列表;

  9. 默认情况下,对于一个实例化了的类模板,其成员只有在使用时才被实例化;

  10. 在一个类模板的作用域内(即在类模板内)定义成员函数可以直接使用模板名而不必指定模板实参,但在类模板外定义成员函数,除了用作用域运算符::指定类外还要指定其模板实参;

  11. 一对一友好关系的声明方法,详见589页,为了让所有实例成为友元,友元声明中必须使用与类模板本身不同的模板参数;

  12. 一个static成员函数只有在使用时才会实例化;

  13. 当我们希望通知编译器一个名字表示类型时,必须使用关键字typename,而不能使用class;

  14. 当我们在类模板外定义一个成员模板时,必须同时为类模板和成员模板提供模板参数列表,类模板的参数列表在前,后跟成员自己的模板参数列表;

16.2 模板实参推断

  1. 将实参传递给带模板类型的函数形参时,能够自动应用的类型转换只有const转换及数组或函数到指针的转换;
    template T fobj(T,T);
    template T fref(const T&, const T&);
    
    int a[10], b[42];
    fobj(a,b) //可行,调用 fobj(int*,int*)
    fref(a,b) //不可行,形参为引用时,数组不会转换为指针,因此a,b类型不匹配
    //实际上调用的是fref(const int(&a)[10], const int(&b)[42])

     

  2. 如果函数参数类型不是模板参数,则对实参进行正常的类型转换;

  3. 显示指定模板实参

    template
    t3 alternative_sum(t2,t1)   //声明OK,但是实例化就必须为三个模板参数指定实参
    
    auto val3 = alternative (i, lng) //错误,t1为long long类型,另外两个无法推测

    正常类型转换可以应用于显式指定的实参,详见604页;

  4. 尾置返回类型处理某些模板返回值类型的确定问题

    template     //It为某容器迭代器类型,要求返回容器内类的引用
    auto &fcn(It beg, It end) ->decltype (*beg)    //尾置返回类型声明方法
    {
        return *beg;                        
    }

     

  5. 进行类型转换的标准库模板类,用法列表(包含remove_reference, add_const等),606页;

  6.  引用折叠只能应用于间接创建的引用的引用,如类型别名或模板参数,有一下折叠方式

    X& &, X& && , X&& &都折叠成类型X& //第一个是引用的引用,第二个是右值引用的引用,第三个是引用的右值引用
    X&& &&折叠成 X&&  //右值引用的右值引用折叠成右值引用

      

16.3 重载与模板

过于抽象,学一段时间再回来补课

你可能感兴趣的:(C++,primer)