Chinaunix首页 | 论坛 | 博客
  • 博客访问: 299126
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: C/C++

2009-07-31 12:23:40

模板本身是一个蓝本(blueprint),它并不是类或者函数。
编译器根据模板实参产生类型明确(typr-specific)的模板实例称为模板实例化。例如标准库vector,使用时 vector myvec,产生一个元素类型为int的vector。编译器重写vector模板,用int替换相应的模板参数。如果再有代码 vector myvec2,编译器会再产生一个元素类型为float的vector实例。

模板在使用时才进行实例化,类模板在引用具体模板类时实例化,函数模板在调用时或用它对函数指针赋值时实例化。

实例化时,模板参数的实参必须与模板形参完全匹配,否则编译器报错。

template <typename T>
func(T para_1, T para_2){
    //....

}

两个同类型的函数参数,可如果我们调用时是以下面的参数类型

func(int,short)

报错为 no matching function for call to `func(int&, short int&)'
注意:如果此函数为普通函数的话,编译器会将第二个参数提升为int型的。而这对于模板参数是不会被转换的。

对于上节的函数指针,当出现这样的重载函数时

但有两个例外,编译器会执行转换而不是产生新实例。
1.模板形参是const引用或指针,而实参是相应类型的非const引用或指针,编译器会执行转换
2.当模板形参是非引用类型时,可以执行普通指针性质的转换,数组指针会被当做指向第一个元素的指针,函数指针也是类似。

template <typename T>
func(T para_1, T para_2){
    //....
}
template <typename T>
func2(T& para_1, T& para_2){
    //....
}
int main(void) {
    int a[10],b[20];
    func(a,b);

    func2(a,b);
    puts("end in main");
    return EXIT_SUCCESS;
}

func会调用成功,而func2则会报错。该实参(引用型)不能向指针进行转换。(书上所说)
section16.cpp:32: no matching function for call to `func2(int[10], int[20])'
但是,如果将数组b改为 int b[10],则会无错误,why

可以用函数模板初始化函数指针

int func(const T para_1, const T para_2){
    //....
    return 1;
}
int (*pf)(const int , const int )=func;

函数指针pf所带的参数类型决定了函数模板func的模板参数类型。

函数模板的显示实参:
  例如一个简单的求两数和并将结果返回函数

template <typename T,typename S,typename U>
T func4(S para_1, U para_2){
    T a=para_1+para_2;
    return a;
}

因为不知道两参数类型,有可能第一个是int,第二个long,也可能相反,故只能选择模板类型的返回值。
但是这样在函数调用时我们没有办法制定 T 类型的实参以使编译器进行参数推断,显式实参在此出现。

long sum=func4<long>(6,7L);
long sum=func4<long>(6L,7);

如此调用就没有问题,显式模板实参以<>括起,其从模板参数最左边第一个开始结合。
在此也可将func4声明为

template <typename T,typename S,typename U>
U func4(T para_1, S para_2){
    U a=para_1+para_2;
    return a;
}

但调用时就得

long sum=func4<long,int,long>(6L,5);
long sum=func4<int,long,long>(6,5L)

不是良好的程序设计风格。

template <typename T>
int func5(const T,const T){
    //....
    return 1;
}
void f6(int (*)(const int ,const int)){}
void f6(int (*)(const double ,const double)){}

f6是重载函数,参数是一个函数指针,有两个版本,当我们想用函数模板func5作为实参时

int main(void) {
    f6(func5);
    return EXIT_SUCCESS;
}

编译器报错:
section16.cpp:52: call of overloaded `f6()' is ambiguous
section16.cpp:42: candidates are: void f6(int (*)(int, int))
section16.cpp:43:                 void f6(int (*)(double, double))
此时我们需要调用时显式指明模板实参

    f6(func5<int>);

阅读(645) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~