[原創(chuàng)文章歡迎轉(zhuǎn)載,但請(qǐng)保留作者信息]
Justin 于 2010-05-11
看到題目我笑了,原來(lái)traits也被大師歸為55式不外傳神功之一。看來(lái)當(dāng)初花的時(shí)間還是值得的啊@#¥%
貌似談到traits都要扯上STL、Boost,大師這回也未能免俗。開(kāi)課就先介紹5種迭代器,input_iterator, output_iterator, forward_interator, bidirectional_iterator 和random_access_iterator。不過(guò)我不想再走老路了,還是自己杜撰些東東來(lái)比較好玩。
大師說(shuō):traits首先應(yīng)該是個(gè)結(jié)構(gòu)體(struct),然后是個(gè)被當(dāng)作類(lèi)來(lái)用的結(jié)構(gòu)體,因?yàn)橛昧斯欣^承來(lái)表示以上5種迭代器的關(guān)系(@#$%)
Traits 也叫“Baggage Class”(Nathan C. Myers, C++ Report, June 1995)。在我看來(lái),traits可以理解為類(lèi)型信息榨取機(jī),制造它的過(guò)程大致分以下幾步,這里來(lái)個(gè)簡(jiǎn)單的例子,我們以不同食物的好吃/不好吃作為食物的類(lèi)型:
1、既然和類(lèi)型信息有關(guān),首先需要知道所有可能的類(lèi)型(如果是void,int之類(lèi)的已經(jīng)類(lèi)型,就可以忽略此步驟),我們的食物有一下兩種類(lèi)型:
struct?yummy?{};
struct?yucky?{};
2、用一個(gè)模板化的traits結(jié)構(gòu)體來(lái)構(gòu)造用于榨取類(lèi)型信息的“吸管”:
template?<typename?T>
struct?food_traits
{
????typedef?typename?T::Taste?taste;
};
上面的“吸管”用來(lái)得到某種食物的好吃/不好吃屬性。“吸管”能工作的前提是:某食物類(lèi)一定要有這一屬性,要么好吃(yummy)要么不好吃(yucky)。
3、然后根據(jù)不同的食物制定不同的模板函數(shù)的重載:
template?<typename?T>
string?doTry?()
{
????return?"well,?i?don't?know?what?this?is?but?i?will?till?take?a?try..";
}
template?<typename?T>
string?doTry(T&,?yummy)
{
????return?"of?course?i?like?this!";
}
template?<typename?T>
string?doTry?(T&,?yucky)
{
????return?"no,keep?it?away?from?me..";
}
4、當(dāng)然,每個(gè)“食物”在制作的過(guò)程中也要加入好吃/不好吃的元素:
class?Cheeseburg
{
????public:
????????typedef?yummy?Taste;
????//..
};
class?Wasabi
{
????public:
????????typedef?yucky?Taste;
????//..
};
5、最后……當(dāng)然就是品嘗食物咯~~
int?main()
{
????Cheeseburg?C;
????Wasabi?W;
????cout?<<?"Cheeseburg??:"?<<?doTry(C,?food_traits<Cheeseburg>::taste())?<<?endl;
????cout?<<?"Wasabi??????????:"?<<?doTry(W,?food_traits<Wasabi>::taste())?<<?endl;
????return?0;
}
這個(gè)例子比較STL或是其他的真實(shí)例程來(lái)說(shuō)比較簡(jiǎn)單明了,而且有我愛(ài)吃的芝士堡,希望你也喜歡:)
不過(guò)在大師的課堂里,其實(shí)還有一步。為了使調(diào)用第3步中的重載模板函數(shù)更簡(jiǎn)單,隱藏不必要的細(xì)節(jié),我們可以再加上一層wrapper函數(shù):
template?<typename?T>
string?Try(T&?food)
{
????return?doTry(food,?typename?food_traits<T>::taste());
}
然后上面的調(diào)用就簡(jiǎn)化為:
//..
cout?<<?"Cheeseburg??:"?<<?Try(W)?<<?endl;
cout?<<?"Wasabi??????????:"?<<?Try(C)?<<?endl;
//..