泛型是 C++ 模板的一个主要用途,另一个应该是元编程了。
我个人理解,泛型的用途有两个,一为去类型封装,二为建立鸭子方法。
- 去类型封装
以 类 C 方式封装一个 int[]
数组
const int len = 10;
class ArrayInt {
private:
int datas[len];
public:
ArrayInt();
int & operator[] (int pos);
};
上述类型只能使用 int
类型,若使用 double
等其他类型,或者不同长度,就要手动重复定义。于是出现模板实现。
template <typename T, int N>
class Array {
private:
T datas[N];
public:
Array();
T & operator[] (int pos);
};
但这种形式,会存在模板的一个问题 —— 若其方法行数很多,不能内联时,不同类型就会产生不同的方法,最终导致编译后的文件特别大。
这时可利用,C 常用去类型的方法。
class Array_impl {
private:
void *datas;
public:
Array_impl(void *p) : datas(p) {}
void *get(int pos, size_t size);
};
template <typename T, int N>
class Array : protected Array_impl {
public:
Array() : Array_impl(new T[N]) {}
T & operator[] (int pos) {
assert(pos < N);
return static_case<T &>(*(Array_impl::get(pos, sizeof(T))));
}
};
- 鸭子类型
当你看到一只鸟走起来像鸭子,游泳起来鸭子,叫起来也像鸭子,那么这只鸟就被称为鸭子类型
T sum(T a, T b) {
return a + b;
}
上面的例子,只要类型 T
存在方法 operator+(T, T) -> T
,那就能通过 sum()
方法了。不管他是什么类型,还是说,他的加法本质实现的是除法,只要存在这个接口,就是好类型。