本文参考文献::GeekBand课堂内容,授课老师:张文杰ios
:C++ Templates 15章节算法
:网络资料: http://blog.csdn.net/my_business/article/details/7891687网络
函数,类或者一些封装的通用算法中的某些部分会由于数据类型不一样而致使处理或逻辑不一样(而咱们又不但愿由于数据类型的差别而修改算法自己的封装时)。traits会是一种很好的解决方案。函数
助教提示:spa
一、不要像用switch同样枚举各个类型,用traits用模板实现。.net
二、第一是但愿会使用traits表达类型信息,由于C++没有C#/Java中相似类型的判断,好比C#里有if (type is SomeType) { … },但C++没有。这个时候考虑用traits表达;第二,但愿注意相似typename CalculatorTraits<T>::ReturnType的返回类型,不要以为奇怪,是模板中经常使用的。指针
根据上面的提示,查阅了C++ Templates,进行以下的分析:code
例一:(C++ Templates Page 240)blog
第一部分输出5个整数的平均值ci
第二部分输出字符的平均值
#include"accum1.h" #include<iostream> int main() { int num[] = {1,2,3,4,5}; // cout<<"The average value of integer valus us" << accum(&num[0],&num[5])/5; char name[] = " templates " int length = sizeof(name) -1; // cout<<"the average value of the characters in \" <<name <<'\n' is" <<accum(&name[0],&name[length])/length <<'\n' ; }
因为咱们是基于char类型进行实例化的,char类型范围很小,很容易出现越界的现象。因此咱们要为该模板的全部用户建立而外的类型。
以下述,要使用这种方法才能够。
accum<int> (&name[0],&name[length])
全部的正常点的用户都会抱怨这样的封装,由于用户不理解为何要让他们去关心本身的模板类型是否越界,用户不明白为何要本身定义输出类型呢?也不明白如何肯定输出类型?
举例二:
template <typename T> class Test { ...... };
Test中的某部分处理会随着类型T的不一样而会有所不一样,好比但愿判断T是否为指针类型,当T为指针类型时的处理有别于非指针类型,怎么作?模板里再加个参数
template <typename T, bool isPointer> class Test { ......// can use isPointer to judge whether T is a pointer };
全部的正常点的用户都会抱怨这样的封装,由于用户不理解为何要让他们去关心本身的模板类型是否为指针,既然是Test类自己的逻辑,为何麻烦用户呢?
解决的方法就是——使用每一个模板的特化来写出这些关联代码
如习题中假设有个计算类Calculator,它要处理int, long, float, double等数值类型。
用模板实现GetLimit()方法,得到每种类型的数值的上限LIMIT,
好比int的上限是100,long的上限是 1000,float的上限是999.99,double的上限是888.8888888等等。
若是采用通用模板T,则不会由于输入类型不一样而返回不一样值。
template <typename T> struct Calculator { public: typename CalculatorHelper<T>::ret_type GetLimit() { return CalculatorHelper<T>::LIMIT; }; private: T mDate; };
Calculator类中,新建一个结构体 Calculatorhelper 来特化全部出现的可能性。若是采用通用模板T,则不会由于输入类型不一样而返回不一样值。
#include "stdafx.h" //普通模板 template <typename T> struct CalculatorHelper { }; //int 特例化,,直接返回LIMIT = 100 template <> struct CalculatorHelper<int> { typedef int ret_type; static ret_type LIMIT; }; //long 特例化,直接返回LIMIT = 1000 template <> struct CalculatorHelper<long> { typedef long ret_type; static ret_type LIMIT; }; //float 特例化,直接返回LIMIT = 999.99 template <> struct CalculatorHelper<float> { typedef float ret_type; static ret_type LIMIT; }; //double 特例化,直接返回LIMIT = 888.8888888 template <> struct CalculatorHelper<double> { typedef double ret_type; static ret_type LIMIT; }; CalculatorHelper<int>::ret_type CalculatorHelper<int>::LIMIT = 100; CalculatorHelper<long>::ret_type CalculatorHelper<long>::LIMIT = 1000; CalculatorHelper<float>::ret_type CalculatorHelper<float>::LIMIT = 999.99; CalculatorHelper<double>::ret_type CalculatorHelper<double>::LIMIT = 888.8888888;
int main() { //int Calculator<int> TestInt; cout << TestInt.GetLimit() << endl; //long Calculator<long> TestLong; cout << TestLong.GetLimit() << endl; //float Calculator<float> TestFloat; cout << TestFloat.GetLimit() << endl; //double Calculator<double> TestDouble; cout.precision(7);//确保7位显示 cout.setf(ios::fixed); cout << TestDouble.GetLimit() << endl; return 0; }
经过上述分析:
咱们把类型不一样的int 、float、double、long,返回值不一样。用户没必要去关心具体的实现细节。只要输入一个类型的数据,就必然返回一个相应的数值。
总结:
函数,类或者一些封装的通用算法中的某些部分会由于数据类型不一样而致使处理或逻辑不一样(而咱们又不但愿由于数据类型的差别而修改算法自己的封装时)。traits会是一种很好的解决方案。
上面仅仅是粗略的理解,还请各位朋友批评指正。
推荐进一步阅读资料:
http://blog.csdn.net/my_business/article/details/8098417
http://blog.csdn.net/zjq2008wd/article/details/41517367