持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
第一次接触到泛型还是 Java 语言,在 Java 中,学习到泛型概念,并用到到了泛型,当时泛型是放宽对类型的约束,是 MVP 设计模式下,通过行为将类进行从新划分为 type 这里可以将其理解 type 而不是 class ,可以将这里 type 理解为型别。
Traits
如何理解 Traits,如果我们直接抛出概念,因为这是一个比较抽象概念,大家理解起来可能不那么容易,这里还是通过一例子,也就是一个问题来引出 Traits,通常提出一个新的方法或者功能都是为了解决问题,我们来写一个算法,很简单就是求和算法,算法名字用 Sigma,因为函数比较简单,只是返回一个集合的所有元素相加的和,所以这里将函数定义为内联函数。然后通过一个模板来让算法可以接受各种类型作为参数。
#include<iostream>
using namespace std;
template <typename T> inline T Sigma(const T const* start, const T const* end)
{
T total = T();
while (start != end) {
total += *start++;
}
return total;
}
注意: 如何构建类型为 T 的初始值 0,此处姑且使用 T(), 对于内置的类型,比如 int、float 等,初始值是 0
int main()
{
int arr[] = { 1,2,3 };
int res;
res = Sigma<int>(arr, arr + 3);
cout << res << endl;
return 0;
}
接下来我们创建一个 char 数组的字符串,然后查看对字符进行求和,这里大家能过猜出 a b c 求和的结果。
char c[] ="abc";
size_t length = strlen(c);
char* p = c;
char* q = c + length;
printf("Sigma(c) = %d\n", Sigma<char>(p, q));
这里创建字符数组为 "abc" Char 类型能够保存 0xFF = 255 也就是 char 类型的能够表示取值范围为 255 。
| 字母 | a | a | a |
|---|---|---|---|
| 97 | 98 | 99 |
(97 + 98 + 99) = 294 这是应该得到结果,其原因是 Char 类型只能保持 255 大小,当试图保存 294 时,就发生了溢出,
为每个 Sigma 函数的参数类型为 T 创建一种关联(association) 关联的类型就是用来存储 Sigma 结果的类型,这种关联可以看作时类型 T 的一种特性(characteristic of the type T),因此 Sigma 函数返回值的类型叫做 T 的 trait,Traits 可以实现为模板类,而关联(association)则是针对每个具体类型 T 的特化,在这个例子里我们将 traits 命名为 SigmaTraits 叫做 traits 模板(trait template)。
template<typename T> class SigmaTraits{};
template <> class SigmaTraits<char> {
public: typedef int ReturnType;
};
template <> class SigmaTraits<int> {
public: typedef long ReturnType;
};
template <> class SigmaTraits<unsigned int> {
public: typedef unsigned long ReturnType;
};
template <> class SigmaTraits<float> {
public: typedef double ReturnType;
};
这里我们就用 Traits 将返回类型与某一个类型相关联,我们定义了一个类 SigmaTraits 这是一个模板类,然后当 T 指定为某一个类,然后为其定义一个特征,也就是将某一个类型与该类型进行关联。
| No | 参数类型 | 返回类型 |
|---|---|---|
| 1 | char | int |
| 2 | char | long |
| 3 | unsigned int | unsigned long |
| 4 | float | double |
template <typename T>
inline typename SigmaTraits<T>::ReturnType Sigma(const T const* start, const T const* end)
{
typedef typename SigmaTraits<T>::ReturnType ReturnType;
ReturnType s = ReturnType();
while (start != end) {
s+= *start++;
}
return s;
}
- 模版类 SigmaTraits 叫做 traits template, 含有其参数类型 T 的一个特性,也就是 ReturnType。返回都是 typename SigmaTraits::ReturnType,虽然传入参数 T 的类型是 char,但是返回的类型却是 int,原因就在于
template<> class SigmaTraits<char>特化将类型 char 的返回值变成 int。