Detailed explanation of the use of function templates for C++ learning

C++ function template

1

2

3

4

5

6

7

8

template<typename T>

void Swap(T &a ,T &b)

{

    T temp;

    temp = a;

    a = b;

    b = temp;

}

When using a template function, the compiler generates the corresponding function definition according to the actual type.

overloaded template

Not all types use the same algorithm, and template function definitions can be overloaded just like regular functions.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

template<typename T>

void Swap(T &a ,T &b); //#1

template<typename T>

void Swap(T *a ,T *b,int n);//#2 最后一个参数是具体类型

int main()

{

    int i =10,j=20;

    Swap(i,j);//使用#1

     

    const int Lim = 8;

    int d1[Lim]={0,1,2,3,4,5,6,7};

    int d2[Lim]={7,6,5,4,3,2,1,0};

    Swap(d1,d2,Lim);//使用#2

}

template<typename T>

void Swap(T &a ,T &b)

{

    T temp;

    temp = a;

    a = b;

    b = temp;

}

template<typename T>

void Swap(T *a ,T *b,int n)

{

    T temp;

    for(int i=0;i<n;i++)

    {

        temp =a[i];

        a[i]=b[i];

        b[i]=temp;

    }

}

Template limitations

Sometimes, the corresponding operation of type T is only applicable to arrays. If T is a structure, the template function will not be established.

Likewise, if(a>b)if T is a structure, then > does not hold

solution:

  • overloaded operators
  • Provide reified template definitions for specific types

show materialization

When the compiler finds a reification definition that matches a function call, it uses that definition and does not look for a template.

  • For a given function name, there can be non-template functions, template functions, and explicitly reified template functions and their respective overloaded versions.
  • Shows that reified prototypes and definitions start with template<>and indicate the type by name
  • The calling order is: non-template function > materialized template function > template function

1

2

3

4

5

6

7

8

void Swap(job& ,job&);

template <typename T>

void Swap(T&,T&);

template<> void Swap<job>(job& ,job&);//显示具体化

//Swap<job>中<job>是可选的,因为函数的参数类型表明,这是job的一个具体化,所以也可以这样写:

template<> void Swap(job& ,job&);

instantiation and concretization

Note: A function template does not generate a function definition, it just generates a scheme for generating a function definition. When the compiler uses a template to generate a function definition for a specific type, it gets a template instance.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

template<typename T>

void Swap(T &a ,T &b);

int a =10,b=20;

Swap(a,b);//因为提供了int类型的参数,所以自动生成了int类型的模板实例。这样是==隐式实例化==

//也可以直接命令编译器创建特定的实例

//显示实例化

template void Swap<int>(int &,int &);//使用Swap()模板生成int类型的函数定义

//显示具体化

template<> void Swap<int>(int& ,int&);

template<> void Swap(int& ,int&);

//区别在于:具体化是不使用Swap()模板函数生成函数定义,而是使用专门为int类型显示定义的函数定义

//简单的理解,具体化是对函数的声明,而实例化是对模板函数的使用

1

2

3

4

5

6

7

8

9

10

11

12

13

template<typename T>

T Add(T a,T b)

{

    return a+b;

}

int m=6;

double x=10.5;

Add<double>(x,m); //与Add(x,m)不匹配,因为一个是int一个是double

                  //通过Add<double>实例化,可强制将m转为double

//但是同样的对Swap便不能成功,因为Swap中使用的是引用类型

Swap<double>(m,x);//double& 不能指向int

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//使用案例

template <typename T>

void Swap(T &,T &);

template<> void Swap<job>(job&,job&);//具体化

int mian()

{

    template void Swap<char>(char& ,char&);

     

    short a,b;

    Swap(a,b);//隐式实例化

     

    job n,m;

    Swap(n,m);//显示具体化

     

    char g,h;

    Swap(g,h);//显示实例化

}

Determination of template function type

1

2

3

4

5

template<class T1,class T2>

void fun(T1 x,T2 y)

{

    ?type? s=x+y; //因为是模板函数,此时?type?类型不确定

}

C++11 adds decltypekeywords

1

2

3

4

5

template<class T1,class T2>

void fun(T1 x,T2 y)

{

    decltype(x+y) s=x+y; //s类型与x+y的类型一致

}

Steps used decltype(expression) var :

1. If expression is not enclosed in parentheses, var is of the same type as expression, including qualifiers such as const

1

2

3

4

5

6

double x =5.5;

double& z =x;

const double* pd;

decltype(x) w; //w为double类型

decltype(z) u; //u为double& 类型

decltype(pd) v; //v为const double* 类型

2. If expression is a function call, var has the same type as the return value. does not actually call the function, the compiler determines the return value type by looking at the prototype

3. If expression is an lvalue, var is a reference to its type. Common situations are as follows:

1

2

3

4

5

6

double x = 4.5;

decltype((x)) r = x;//r是double&类型

decltype(x) r = x;//r是double类型

//括号不会改变expression的值和左值性

//可理解为加括号仅仅是decltype声明引用的一种方式

4. If none of the first 3 items are satisfied, then var has the same type as expression

1

2

3

4

5

6

int j=3;

int &k=j;

int &n=j;

decltype(j+6) x; //x是int

decltype(k+n) y;//y是int ,虽然k和n是引用,但是k+n不是引用是2个int的和

If declared multiple times, can be combined typedefwithdecltype

1

2

3

typedef decltype(x+y) xytype;

xytype z = x+y;

xytype arr[10];

However, some function templates that need to define the return value type still cannot be resolved, such as:

1

2

3

4

5

template<class T1,class T2>

?type? fun(T1 x,T2 y) //此时无法确定类型

{

    return x+y;

}

C++新增语法auto h(int x,float y) -> double,这称为后置返回类型,auto是一个占位符

1

2

3

4

5

template<class T1,class T2>

auto fun(T1 x,T2 y)->decltype(x+y) //后置类型使用decltype

{

    return x+y;

}

Guess you like

Origin blog.csdn.net/sinat_40572875/article/details/129303035