首页 > 代码库 > [c++] Templates

[c++] Templates

Template是编译时多态。所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态。

 

Function Template

A function template is a prescription for the compiler to generate particular instances of a function varying by type.

”变量类型“的部分放在一块,与“变量类型无关”的部分放在另一边。

放在"头文件“中,声明和实现建议这么做。其他方式不推荐。

 

Name Resolution

  • designer & client
  • Only three kinds of implicit conversions for type parameters:

技术分享

 

参数的类型不同的数字比较的话,例如:int , double

使用例如:min(static_cast<double> i, d)的方式。

 

decltype (不用类型转换,编译器自己推导)

编译时类型推导,除了我们说过的auto关键字,还有本文的decltype。

(1) 解决模板函数返回值不确定情况:

template <typename T, typename U>auto mymin(T a, U b) -> decltype(a < b ? a : b) {    return a < b ? a: b;}

泛型编程中结合auto,用于追踪函数的返回值类型!

 

(2) 根据变量推导齐类型:

int i;const &j = i;int *p = i;int k;decltype(i) x; // int x: i is a variabledecltype(j) y = k; // int &y = k: j is an lvaluedecltype(*p) z = k; // int &z = k: *p is an lvaluedecltype((i)) w = k; // int &w = k: (i) is an lvalue

Ref: C++11特性:decltype关键字

 

(3) 与using/typedef合用,用于定义类型:

using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型using ptrdiff_t = decltype((int*)0 - (int*)0);using nullptr_t = decltype(nullptr);
vector<int >vec;typedef decltype(vec.begin()) vectype;for (vectype i = vec.begin; i != vec.end(); i++){    //...}
 

(4) 重用匿名类型:

在C++中,我们有时候会遇上一些匿名类型,而借助decltype,我们可以重新使用这个匿名的结构体:

struct {    int d ;    doubel b;}anon_s;
decltype(anon_s) as ; //定义了一个上面匿名的结构体

 

decltype推导四规则

  1. 如果e是一个没有带括号的标记符表达式或者类成员访问表达式,那么的decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译错误。
  2. 否则 ,假设e的类型是T,如果e是一个将亡值,那么decltype(e)为T&&
  3. 否则,假设e的类型是T,如果e是一个左值,那么decltype(e)为T&。
  4. 否则,假设e的类型是T,则decltype(e)为T。

注意小括号的作用:
int func(void){    int i = 10;     decltype(i) a = i;    decltype((i)) b = i;    a = 10;     cout << "i = " << i << endl;    b = 20;   // b变为 引用    cout << "i = " << i << endl;    return 0;}

 

技术分享
int decipline(void){    int i = 4;    int arr[5] = { 0 };    int *ptr = arr;    struct S{ double d; }s ;//    void Overloaded(int);//    void Overloaded(char);//重载的函数    int && RvalRef();    const bool Func(int);    //规则一:推导为其类型    decltype (arr) var1; //int 标记符表达式    decltype (ptr) var2;//int *  标记符表达式    decltype(s.d) var3;//doubel 成员访问表达式    //decltype(Overloaded) var4;//重载函数。编译错误。    //规则二:将亡值。推导为类型的右值引用。    decltype (RvalRef()) var5 = 1;    //规则三:左值,推导为类型的引用。    decltype ((i))var6 = i;     //int&    decltype (true ? i : i) var7 = i; //int&  条件表达式返回左值。    {        int x = 10;        float y = 1.11;        decltype(true?x:y) c = (false?x:y);        cout << "c = " << c << endl;    }    decltype (++i) var8 = i; //int&  ++i返回i的左值。    decltype(arr[5]) var9 = i;//int&. []操作返回左值    decltype(*ptr)var10 = i;//int& *操作返回左值    decltype("hello")var11 = "hello"; //const char(&)[9]  字符串字面常量为左值,且为const左值。    //规则四:以上都不是,则推导为本类型    decltype(1) var12;//const int    decltype(Func(1)) var13=true;//const bool    decltype(i++) var14 = i;//int i++返回右值    return 0;}
四个规则的示例


左值推导为类型的引用:
如何判断是否是左值呢?
cout << is_lvalue_reference<decltype(++i)>::value << endl;

 

 


模板的健壮性

 若要比较字符串,使用函数override.

const char *s = "xyz";const char *t = "abc";

/* 返回了数字,认为是地址,也就是数组的首地址 */cout
<< min(s, t) << endl;

 

模板的设计 更加健壮。如下:

技术分享

 

 

 template function的默认参数 也可以设置,实现健壮性

技术分享

 

 

template‘s variadic function ,进一步健壮

 技术分享

注意关键写法:

template <typename A, typename... B>void print(A head, B... tail) {  ...  }

 

continue...

[c++] Templates