1.1.定义:模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。
typename标识嵌套从属类型名称, 但不需在基类列表和成员初始化列表内使用.
1.2.分类:
1)从属名称: 模板(template)内出现的名称, 相依于某个模板(template)参数, 如T t;
2)嵌套从属名称:从属名称在class内呈嵌套装, 如T::const_iterator ci;
3)非从属名称 : 不依赖任何template参数的名称, 如int value;
1.3.class,typename的区别:
1)在声明模板参数时,class和typename可互换
2)嵌套依赖类型名:必用typename去标识嵌套依赖类型名;(不能用class)
格式:typename 嵌套依赖类型名;
例外:基类标识符在基类列表中或在成员初始化列表中省略typename;
实例1.1:模板参数-函数
template <typename T1, class T2>
inline const T1 max(const T1 &x, const T2 &y)
{T1 z = T1(y); return (x < z)? z : x;}
inline const int Max(const int &x, const float &y)
{int z = int(y); return (x < z)? z : x;}
int main(){
size_t x = 6; float y = 8;
cout << max(x, y) << endl;//8
cout << Max(x, y) << endl;//8
}
实例1.2:模板参数-类
template<class T1, typename T2>
class A {
private:
T1 x;
T2 y;
public:
A(T1 x = 0, T2 y = 0);
A add(const A<T1, T2> &a)const;
void show()const;
};
template<class T1, typename T2>
A<T1, T2>::A(T1 x, T2 y) :x(x), y(y) {}
template<class T1, typename T2>
A<T1, T2> A<T1, T2>::add(const A<T1, T2> &a)const
{return A<T1, T2>(x + a.x, y + a.y);}
template<class T1, typename T2>
void A<T1, T2>::show()const { cout << "[" << x << "," << y << "]" << endl; }
int main() {
A<int,double> x(1, 2.2), y(2, 3.3), z;
z = x.add(y);
z.show(); //[3,5.5]
}
实例2.1:嵌套依赖类型:内部成员的嵌套依赖
struct STRUCT_INT_TYPE{typedef int INT_TYPE;};
template <typename T>
void foo(const T& t){
/*
声明类型为T::INT_TYPE对象的指针
typename说明T::INT_TYPE是一个类型名而不是变量名
注意:
任何含有名为“INT_TYPE”项的类T,都可被当作模板参数传入foo()函数,包括typedef类型、枚举类型或变量等
*/
typename T::INT_TYPE * p;
//T::INT_TYPE * p;//错误
//编译器默认INT_TYPE为变量名,而非类型名;
//T::INT_TYPE * p 其中“*”被解释为乘法;结果为INT_TYPE(变量)*p(变量)
int x = 10;
p = &x;
printf("p=%p;*p=%d", p, *p);//p=000000499C9FFB54;*p=10
}
int main(){
STRUCT_INT_TYPE int_type ;
foo(int_type);
}
实例2.2: 嵌套从属类型名称, 如果是基类列表和成员初值列中, 不使用typename;
#include <iostream>
#include <vector>
using namespace std;
struct STRUCT_TYPE {
STRUCT_TYPE(int x) { cout << "x=" << x << endl; }
};
template<typename T> //必须添加
struct Base { typedef STRUCT_TYPE STRUCT_OBJ; };
template<typename T>
class A : public Base<T>::STRUCT_OBJ { //不用typename
public:
explicit A(int x) : Base<T>::STRUCT_OBJ(x) { //不用typename
typename Base<T>::STRUCT_OBJ temp(7); //必须使用
}
};
int main() {
A<int> d(5);
}
输出:
Number = 5
Number = 7
实例3:当使用特性类(traits class)时, 必须使用typename, 如
template<typename T>
void func(T iter)
{
typedef typename std::iterator_traits<T>::value_type value_type; //使用typename
value_type temp(*iter);
cout << "temp = " << temp << endl;
}
int main() {
std::array<int, 5> arr = { 1,2,3,4,5 };
std::array<int, 5>::iterator iter = arr.begin()+2;
func(iter);
}
输出:temp = 1
实例4:vector模板类
#include <stdio.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
#define TEMPLATE_TYPE_T1_T2 template <typename T1, class T2>
TEMPLATE_TYPE_T1_T2
class Array {
private:
T1 len;
vector<T2> vec;
public:
Array() {}
Array(T1 len);
Array(const Array &b);
Array(const T2*p, T1 len); //vector<int> val{ vector<int>(5,0) };
void operator=(const Array &a);
~Array() {};
T1 get_len(void);
void set_len(T1 len);
void resize(const T1 len, T2 val = T2(0));//只能在声明(非定义)中定义默认参数
void view();
};
TEMPLATE_TYPE_T1_T2
Array<T1,T2>::Array(T1 len) { this->len = len; vec.resize(len, T2(0)); }
TEMPLATE_TYPE_T1_T2
Array<T1, T2>::Array(const Array &b) { len = b.len; vec = b.vec; }
TEMPLATE_TYPE_T1_T2
Array<T1, T2>::Array(const T2*p, T1 len) { this->len = len; vector<T2> vec1(p, p + len); vec = vec1; }
TEMPLATE_TYPE_T1_T2
void Array<T1, T2>::operator=(const Array &a) { len = a.len; vec = a.vec; }
TEMPLATE_TYPE_T1_T2
T1 Array<T1, T2>::get_len(void) { return len; }
TEMPLATE_TYPE_T1_T2
void Array<T1, T2>::set_len(T1 len) { this->len = len; resize(len); }
TEMPLATE_TYPE_T1_T2
void Array<T1, T2>::resize(const T1 len, T2 val) { vec.resize(len, val); }//不允许使用默认参数
TEMPLATE_TYPE_T1_T2
void Array<T1, T2>::view()
{
cout << "{\"len\":" << vec.size() << ",\"vec\":[";
for (T1 i = 0; i < vec.size(); i++) cout << vec.at(i) << ",";
cout << "]}" << endl;
}
class ARRAY {
private:
size_t len;
vector<float> vec;
public:
ARRAY() {}
ARRAY(size_t len);
ARRAY(const ARRAY &b);
ARRAY(const float*p, size_t len); //vector<int> val{ vector<int>(5,0) };
void operator=(const ARRAY &a);
~ARRAY() {};
size_t get_len(void);
void set_len(size_t len);
void resize(const size_t len,float val = float(0));//只能在声明(非定义)中定义默认参数
void view();
};
ARRAY::ARRAY(size_t len) { this->len = len; vec.resize(len, float(0)); }
ARRAY::ARRAY(const ARRAY &b) { len = b.len; vec = b.vec; }
ARRAY::ARRAY(const float*p, size_t len){this->len = len; vector<float> vec1(p, p + len); vec = vec1;}
void ARRAY::operator=(const ARRAY &a) { len = a.len; vec = a.vec; }
size_t ARRAY::get_len(void) { return len; }
void ARRAY::set_len(size_t len) { this->len = len; resize(len); }
void ARRAY::resize(const size_t len, float val ) { vec.resize(len, val); }//不允许使用默认参数
void ARRAY::view()
{
cout <<"{\"len\":"<< vec.size() << ",\"vec\":[";
for (size_t i = 0; i < vec.size(); i++) cout << vec.at(i) << ",";
cout << "]}" << endl;
}
int main(){
//测试类
Array<size_t,float> a1,a2(x),a3(a2),a4(arr1,4);
a1.view(); a2.view(); a3.view(); a4.view();
a1 = a4; a2 = a4; a3 = a4;
a1.view(); a2.view(); a3.view(); a4.view();
a4.resize(6);
a4.view();
return 0;
}
/*
{"len":0, "vec" : []}
{"len":6, "vec" : [0, 0, 0, 0, 0, 0, ]}
{"len":6, "vec" : [0, 0, 0, 0, 0, 0, ]}
{"len":4, "vec" : [1, 2, 3, 4, ]}
{"len":4, "vec" : [1, 2, 3, 4, ]}
{"len":4, "vec" : [1, 2, 3, 4, ]}
{"len":4, "vec" : [1, 2, 3, 4, ]}
{"len":4, "vec" : [1, 2, 3, 4, ]}
{"len":6, "vec" : [1,2,3,4,0,0,]}
*/