本文參考文獻::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