最近在群裡面看到這樣一個語句:typedef typename T::value_type _type; 我的第一反應這是一個自定義類型,沒錯確實是一句自定義類型,但這和我們平常見到的自定義類型又有不同,T::value_type 這塊會讓大多數人和很不解。其實他的意義就是:這個T必須含有value_type這個成員,也就是說T必須是個類或者命名空間,如果還不明白繼續往下看。
[cpp]
// 自定義類型1-這是常規自定義類型的變形,首先傳入的classType應該是個類且必須有value_type這個成員,例如STL中的類.
template<class classType,class keyType = int,class valueType = char*>
struct CCustomType
{
typedef typename classType::value_type custom_type;
custom_type data;
};
使用CCustomType自定義類型:
[cpp]
CCustomType<string> string_;
string_.data = 'c'; // string::value_type 是char 類型,從下面的basic_string就可以看出
CCustomType<basic_string<char,char_traits<char>,allocator<char>>> string_2;
string_2.data = 'x'; // char
CCustomType<list<char*>> list_;
list_.data = "you are so beautiful"; // char*
CCustomType<set<UINT>> set_;
set_.data = 512139461; // UINT
聲明CCustomType<map<int,char*>,int,char*> pair_;
這裡pair_.data 是map的成員value_type也就是pair類型,更具體的講是pair<int,char*> #
在使用CCustomType<map<int,char*>,int,char*>之前,我們先看下stl中pair的用法:
[cpp]
std::pair<int,char*> pair_1(2012,"hello world"); // 利用構造函數初始化pair_1
//
std::pair<int,char*> pair_2;
pair_2 = make_pair(1989,(char*)"hansen"); // ok make_pair賦值
//
pair_2.first = 2000; // ok
pair_2.second = "just test"; // ok
//
map<int,char*> nMap;
nMap.insert(pair_1);
nMap.insert(pair_2);
CCustomType<map<int,char*>,int,char*> pair_;// ok map應該這樣用,key是int型 ,value是char*類型
//(pair_.data).first = 2012; error C3892: “pair_”: 不能給常量賦.
//通過監視查看pair_.data.first是個const int類型為什麼會變成const int,我傳入的是<int,char*>類型,應該是pair<int,char*>類型,開始我也有這個疑問.
(pair_.data).second = "that's ok"; // ok,value不是const的,可以賦值
分析:
[cpp]
//按照上面的原型,聲明一個pair類型變量 pair_test
map<int,char*>::value_type pair_test(2013,"test test");
// 通過源碼一步步跟進查看這個map的value_type,first:const int ,second:char*
// 1.map的value_type來自_Mybase的成員value_type:
typedef typename _Mybase::value_type value_type;
// 2.繼續跟發現_Mybase是個模板類,由_Tmap_traits構造:
typedef _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false> > _Mybase;
// 3.就要揭曉答案了,跟_Tmap_traits發現原來他自定義了pair類型:
typedef pair<const _Kty, _Ty> value_type;
// 4.這就是為什麼map的key是個const類型,也表明上面的自定義類型CCustomType的data成員實際上是個pair<const T,T>
那麼有什麼辦法可以給自定義類型CCustomType的data成員賦值呢,答案是通過構造函數,我們先對CCustomType做下變形:
[cpp]
template<class classType,class keyType = int,class valueType = char*>
struct CCustomTypeEx
{
typedef typename classType::value_type custom_type;
custom_type data;
CCustomTypeEx() {}
CCustomTypeEx(keyType _key,valueType _value)
:data(_key,_value) // 調用classType::pair的構造函數
{
}
}; www.2cto.com
[cpp]
CCustomTypeEx<map<int,char*>,int,char*> pair_ex(1989,"hansen"); // ok
總結:關於CCustomType<map,int,char*> pair_那個問題,其實在一開始我就偷換掉了概念,前面有句打#的就是理解不完全,死死認定pair_.data是個pair類型堅信pair是可以在構造後賦值的,沒錯常規的pair確實可以這樣做,但我忘記了CCustomType中關鍵的一句typedef typename classType::value_type custom_type;也就是說這個value_type一定要是classType的成員,所以pair_.data 應該是map::value_type類型,進一步就是pair<const int,char*>類型.