SGI STL學習筆記(2):traits程式設計技法
轉自 http://blog.csdn.net/my_business/article/details/7891687
開門見山,什麼是traits?
其實它並不是一個新的概念,上個世紀90年代中期就已經被提出,只是到了這個世紀才在各個C++庫中被廣泛使用,而我也是在這個概念誕生十多年後才接觸到它。C++之父Bjarne Stroustrup對traits有如下的描述:
Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine “policy” or “implementation details”.
我不知道官方或一些書上是如何去解釋traits的,我的理解是:
當函式,類或者一些封裝的通用演算法中的某些部分會因為資料型別不同而導致處理或邏輯不同(而我們又不希望因為資料型別的差異而修改演算法本身的封裝時),traits會是一種很好的解決方案。
下面通過實際程式碼來說明。
例1:
先看這樣一個例子。如果有一個模板類Test:
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類當前T是否為指標。如:Test<int*, true>
很抱歉,所有正常點的使用者都會抱怨這樣的封裝,因為使用者不理解為什麼要讓他們去關心自己的模板型別是否為指標,既然是Test類本身的邏輯,為什麼要麻煩使用者呢?
由於我們很難去限制使用者在使用模板類時是使用指標還是基本資料型別還是自定義型別,而用常規方法也沒有很好的方法去判斷當前的T的型別。traits怎麼做呢?
定義traits結構:
template <typename T>
struct TraitsHelper {
static const bool isPointer = false;
};
template <typename T>
struct TraitsHelper<T*> {
static const bool isPointer = true;
};
也許你會很困惑,結構體裡就一個靜態常量,沒有任何方法和成員變數,有什麼用呢?解釋一下,第一個結構體的功能是定義所有TraitsHelper中isPointer的預設值都是false,而第二個結構體的功能是當模板型別T為指標時,isPointer的值為true。也就是說我們可以這樣來判斷當前型別,如下:
TraitsHelper<int>::isPointer值為false, 可以得出當前型別int非指標型別
TraitsHelper<int*>::isPointer值為true, 可以得出當前型別int*為指標型別
也許看到這裡部分人會認為我簡直是在說廢話,請再仔細品味下,這樣是否就可以在上面Test類的定義中直接使用TraitsHelper<T>::isPointer來判斷當前T的型別了。
if (TraitsHelper<T>::isPointer)
......
else
......
例2:
再看第二個例子:
還是一個模板類Test:
template <typename T>
class Test {
public:
int Compute(int d);
private:
T mData;
};
它有一個Compute方法來做一些計算,具有int型的引數並返回int型的值。
現在需求變了,需要在T為int型別時,Compute方法的引數為int,返回型別也為int,當T為float時,Compute方法的引數為float,返回型別為int,而當T為其他型別,Compute方法的引數為T,返回型別也為T,怎麼做呢?還是用traits的方式思考下:
template <typename T>
struct TraitsHelper {
typedef T ret_type;
typedef T par_type;
};
template <>
struct TraitsHelper<int> {
typedef int ret_type;
typedef int par_type;
};
template <>
struct TraitsHelper<float> {
typedef int ret_type;
typedef float par_type;
};
然後我們再把Test類也更新下:
template <typename T>
class Test {
public:
typename TraitsHelper<T>::ret_type Compute(typename TraitsHelper<T>::par_type d);
private:
T mData;
};
可見,我們把因型別不同而引起的變化隔離在了Test類以外,對使用者而言完全不需要去關心這些邏輯,他們甚至不需要知道我們是否使用了traits來解決了這個問題。
到這裡,再讓我們回過來去品味下開始的那句話:
當函式,類或者一些封裝的通用演算法中的某些部分會因為資料型別不同而導致處理或邏輯不同時,traits會是一種很好的解決方案。
相關文章
- 【STL 原始碼剖析】淺談 STL 迭代器與 traits 程式設計技法原始碼AI程式設計
- SGI STL學習筆記(1):空間配置器(allocator)筆記
- SGI STL學習筆記(3):copy演算法實現細節筆記演算法
- SGI STL 的記憶體管理記憶體
- STL-空間配置器、迭代器、traits程式設計技巧AI程式設計
- Java程式設計思想(2nd)學習筆記(9)-2 (轉)Java程式設計筆記
- Java程式設計思想(2nd)學習筆記(8)-2 (轉)Java程式設計筆記
- 網路程式設計學習筆記程式設計筆記
- 系統程式設計學習筆記程式設計筆記
- Linux學習/TCP程式設計學習筆記LinuxTCP程式設計筆記
- 《WebGL程式設計指南》學習筆記——2.使用< canvas >元素Web程式設計筆記Canvas
- Java程式設計思想(2nd)學習筆記(7) (轉)Java程式設計筆記
- Java程式設計思想(2nd)學習筆記(6) (轉)Java程式設計筆記
- Linux程式設計學習筆記 | Linux IO學習[2] – 標準IOLinux程式設計筆記
- STL的學習筆記之一 (轉)筆記
- Golang 學習筆記——tun/tap 程式設計Golang筆記程式設計
- 結構化程式設計--學習筆記程式設計筆記
- Javascript高階程式設計 學習筆記JavaScript程式設計筆記
- ROS串列埠程式設計學習筆記ROS串列埠程式設計筆記
- spark學習筆記--進階程式設計Spark筆記程式設計
- Linux Shell 程式設計學習筆記Linux程式設計筆記
- 《Windows 程式設計》學習筆記(五) (轉)Windows程式設計筆記
- 《Windows 程式設計》學習筆記(四) (轉)Windows程式設計筆記
- 《Windows 程式設計》學習筆記(三) (轉)Windows程式設計筆記
- 林軒田機器學習技法課程學習筆記2 — Dual Support Vector Machine機器學習筆記Mac
- Python3:物件導向程式設計學習筆記(2)Python物件程式設計筆記
- <<SQL Server 2005 高階程式設計>> 學習筆記(2)SQLServer程式設計筆記
- Java程式設計思想(2nd)學習筆記(8)-1 (轉)Java程式設計筆記
- 四. 文字程式設計--Windows程式設計課程學習筆記程式設計Windows筆記
- 設計模式學習筆記設計模式筆記
- 學習筆記-設計模式筆記設計模式
- 好程式設計師web前端培訓學習筆記Vue學習筆記一程式設計師Web前端筆記Vue
- C++ 學習筆記之——STL 庫 queueC++筆記
- C++ 學習筆記之 STL 佇列C++筆記佇列
- 好程式設計師學習筆記:函式程式設計師筆記函式
- Vue學習筆記(九):元件化程式設計Vue筆記元件化程式設計
- nginx學習筆記(6):程式模型的設計Nginx筆記模型
- Java學習筆記--網路程式設計SocketJava筆記程式設計