Where there is a dream ,there is hope
C++博客
::
首頁(yè)
::
聯(lián)系
::
聚合
::
管理
64 Posts :: 0 Stories :: 8 Comments :: 0 Trackbacks
常用鏈接
我的隨筆
我的評(píng)論
我參與的隨筆
留言簿
(1)
給我留言
查看公開(kāi)留言
查看私人留言
我參與的團(tuán)隊(duì)
隨筆分類
C#(2)
C/C++(19)
EFFECTIVE-STL學(xué)習(xí)筆記(3)
Mono
monodevelop
TCP/IP(1)
翻譯文章(4)
算法/數(shù)據(jù)結(jié)構(gòu)(1)
折騰UBUNTU(2)
職業(yè)人生(1)
隨筆檔案
2011年11月 (1)
2011年10月 (7)
2011年9月 (2)
2011年8月 (7)
2011年7月 (3)
2011年6月 (5)
2011年4月 (2)
2011年3月 (5)
2011年2月 (8)
2011年1月 (1)
2010年12月 (7)
2010年11月 (9)
2010年10月 (4)
2010年7月 (3)
收藏夾
生活思考(1)
C++
C#講師-設(shè)計(jì)模式-數(shù)據(jù)結(jié)構(gòu)
范懷宇
韓湘子
專門(mén)解決各種C++疑難雜癥
搜索
最新評(píng)論
1.?re: 匿名空間
.就空間看快樂(lè)
--何霞飛
2.?re: 匿名空間
u厲害
--何霞飛
3.?re: 服務(wù)器設(shè)計(jì)-轉(zhuǎn)
這種文章挺少的噢。不是做服務(wù)器的,多了解一些總是好的。設(shè)計(jì)真是一門(mén)有意思的學(xué)問(wèn)。
--K.V
4.?re: josephon問(wèn)題
不過(guò)這個(gè)模擬過(guò)程非常不好,對(duì)于100000以上的人數(shù)來(lái)說(shuō)簡(jiǎn)直就是悲劇。。。
--Husiwa
5.?re: 簡(jiǎn)潔的字符串連接函數(shù)
@木頭奎
的確有缺點(diǎn),但這個(gè)函數(shù)的實(shí)現(xiàn)過(guò)程還是有其發(fā)作的
--Husiwa
閱讀排行榜
1.?轉(zhuǎn)載:vector find(2382)
2.?vector 查找指定元素(1777)
3.?C#結(jié)構(gòu)體序列化(1264)
4.?windows.h與winsock2.h的包含順序(1161)
5.?模板類靜態(tài)變量初始化(1122)
評(píng)論排行榜
1.?簡(jiǎn)潔的字符串連接函數(shù)(2)
2.?匿名空間(2)
3.?C++指針探討 (一)數(shù)據(jù)指針(1)
4.?josephon問(wèn)題(1)
5.?服務(wù)器設(shè)計(jì)-轉(zhuǎn)(1)
轉(zhuǎn)載 typename
C++箴言:理解typename的兩個(gè)含義 問(wèn)題:在下面的 template declarations(模板聲明)中 class 和 typename 有什么不同?
template
<
class
T
>
class
Widget;
//
uses "class"
template
<
typename T
>
class
Widget;
//
uses "typename"
答案:沒(méi)什么不同。在聲明一個(gè) template type parameter(模板類型參數(shù))的時(shí)候,class 和 typename 意味著完全相同的東西。一些程序員更喜歡在所有的時(shí)間都用 class,因?yàn)樗菀纵斎搿F渌耍òㄎ冶救耍└矚g typename,因?yàn)樗凳局@個(gè)參數(shù)不必要是一個(gè) class type(類類型)。少數(shù)開(kāi)發(fā)者在任何類型都被允許的時(shí)候使用 typename,而把 class 保留給僅接受 user-defined types(用戶定義類型)的場(chǎng)合。但是從 C++ 的觀點(diǎn)看,class 和 typename 在聲明一個(gè) template parameter(模板參數(shù))時(shí)意味著完全相同的東西。
然而,C++ 并不總是把 class 和 typename 視為等同的東西。有時(shí)你必須使用 typename。為了理解這一點(diǎn),我們不得不討論你會(huì)在一個(gè) template(模板)中涉及到的兩種名字。
假設(shè)我們有一個(gè)函數(shù)的模板,它能取得一個(gè) STL-compatible container(STL 兼容容器)中持有的能賦值給 ints 的對(duì)象。進(jìn)一步假設(shè)這個(gè)函數(shù)只是簡(jiǎn)單地打印它的第二個(gè)元素的值。它是一個(gè)用糊涂的方法實(shí)現(xiàn)的糊涂的函數(shù),而且就像我下面寫(xiě)的,它甚至不能編譯,但是請(qǐng)將這些事先放在一邊——有一種方法能發(fā)現(xiàn)我的愚蠢:
template
<
typename C
>
//
print 2nd element in
void
print2nd(
const
C
&
container)
//
container;
{
//
this is not valid C++!
if
(container.size()
>=
2
)
{
C::const_iterator iter(container.begin());
//
get iterator to 1st element
++
iter;
//
move iter to 2nd element
int
value
=
*
iter;
//
copy that element to an int
std::cout
<<
value;
//
print the int
}
}
我突出了這個(gè)函數(shù)中的兩個(gè) local variables(局部變量),iter 和 value。iter 的類型是 C::const_iterator,一個(gè)依賴于 template parameter(模板參數(shù))C 的類型。一個(gè) template(模板)中的依賴于一個(gè) template parameter(模板參數(shù))的名字被稱為 dependent names(依賴名字)。當(dāng)一個(gè) dependent names(依賴名字)嵌套在一個(gè) class(類)的內(nèi)部時(shí),我稱它為 nested dependent name(嵌套依賴名字)。C::const_iterator 是一個(gè) nested dependent name(嵌套依賴名字)。實(shí)際上,它是一個(gè) nested dependent type name(嵌套依賴類型名),也就是說(shuō),一個(gè)涉及到一個(gè) type(類型)的 nested dependent name(嵌套依賴名字)。
print2nd 中的另一個(gè) local variable(局部變量)value 具有 int 類型。int 是一個(gè)不依賴于任何 template parameter(模板參數(shù))的名字。這樣的名字以 non-dependent names(非依賴名字)聞名。(我想不通為什么他們不稱它為 independent names(無(wú)依賴名字)。如果,像我一樣,你發(fā)現(xiàn)術(shù)語(yǔ) "non-dependent" 是一個(gè)令人厭惡的東西,你就和我產(chǎn)生了共鳴,但是 "non-dependent" 就是這類名字的術(shù)語(yǔ),所以,像我一樣,轉(zhuǎn)轉(zhuǎn)眼睛放棄你的自我主張。)
nested dependent name(嵌套依賴名字)會(huì)導(dǎo)致解析困難。例如,假設(shè)我們更加愚蠢地以這種方法開(kāi)始 print2nd:
template
<
typename C
>
void
print2nd(
const
C
&
container)
{
C::const_iterator
*
x;
//
}
這看上去好像是我們將 x 聲明為一個(gè)指向 C::const_iterator 的 local variable(局部變量)。但是它看上去如此僅僅是因?yàn)槲覀冎?C::const_iterator 是一個(gè) type(類型)。但是如果 C::const_iterator 不是一個(gè) type(類型)呢?如果 C 有一個(gè) static data member(靜態(tài)數(shù)據(jù)成員)碰巧就叫做 const_iterator 呢?再如果 x 碰巧是一個(gè) global variable(全局變量)的名字呢?在這種情況下,上面的代碼就不是聲明一個(gè) local variable(局部變量),而是成為 C::const_iterator 乘以 x!當(dāng)然,這聽(tīng)起來(lái)有些愚蠢,但它是可能的,而編寫(xiě) C++ 解析器的人必須考慮所有可能的輸入,甚至是愚蠢的。
直到 C 成為已知之前,沒(méi)有任何辦法知道 C::const_iterator 到底是不是一個(gè) type(類型),而當(dāng) template(模板)print2nd 被解析的時(shí)候,C 還不是已知的。C++ 有一條規(guī)則解決這個(gè)歧義:如果解析器在一個(gè) template(模板)中遇到一個(gè) nested dependent name(嵌套依賴名字),它假定那個(gè)名字不是一個(gè) type(類型),除非你用其它方式告訴它。缺省情況下,nested dependent name(嵌套依賴名字)不是 types(類型)。(對(duì)于這條規(guī)則有一個(gè)例外,我待會(huì)兒告訴你。)
記住這個(gè),再看看 print2nd 的開(kāi)頭:
template
<
typename C
>
void
print2nd(
const
C
&
container)
{
if
(container.size()
>=
2
) {
C::const_iterator iter(container.begin());
//
this name is assumed to
//
not be a type
這為什么不是合法的 C++ 現(xiàn)在應(yīng)該很清楚了。iter 的 declaration(聲明)僅僅在 C::const_iterator 是一個(gè) type(類型)時(shí)才有意義,但是我們沒(méi)有告訴 C++ 它是,而 C++ 就假定它不是。要想轉(zhuǎn)變這個(gè)形勢(shì),我們必須告訴 C++ C::const_iterator 是一個(gè) type(類型)。我們將 typename 放在緊挨著它的前面來(lái)做到這一點(diǎn):
template
<
typename C
>
//
this is valid C++
void
print2nd(
const
C
&
container)
{
if
(container.size()
>=
2
) {
typename C::const_iterator iter(container.begin());
}
}
通用的規(guī)則很簡(jiǎn)單:在你涉及到一個(gè)在 template(模板)中的 nested dependent type name(嵌套依賴類型名)的任何時(shí)候,你必須把單詞 typename 放在緊挨著它的前面。(重申一下,我待會(huì)兒要描述一個(gè)例外。)
typename 應(yīng)該僅僅被用于標(biāo)識(shí) nested dependent type name(嵌套依賴類型名);其它名字不應(yīng)該用它。例如,這是一個(gè)取得一個(gè) container(容器)和這個(gè) container(容器)中的一個(gè) iterator(迭代器)的 function template(函數(shù)模板):
template
<
typename C
>
//
typename allowed (as is "class")
void
f(
const
C
&
container,
//
typename not allowed
typename C::iterator iter);
//
typename required
C 不是一個(gè) nested dependent type name(嵌套依賴類型名)(它不是嵌套在依賴于一個(gè) template parameter(模板參數(shù))的什么東西內(nèi)部的),所以在聲明 container 時(shí)它不必被 typename 前置,但是 C::iterator 是一個(gè) nested dependent type name(嵌套依賴類型名),所以它必需被 typename 前置。
"typename must precede nested dependent type names"(“typename 必須前置于嵌套依賴類型名”)規(guī)則的例外是 typename 不必前置于在一個(gè) list of base classes(基類列表)中的或者在一個(gè) member initialization list(成員初始化列表)中作為一個(gè) base classes identifier(基類標(biāo)識(shí)符)的 nested dependent type name(嵌套依賴類型名)。例如:
template
<
typename T
>
class
Derived:
public
Base
<
T
>
::Nested {
//
base class list: typename not
public
:
//
allowed
explicit
Derived(
int
x)
: Base
<
T
>
::Nested(x)
//
base class identifier in mem
{
//
init. list: typename not allowed
typename Base
<
T
>
::Nested temp;
//
use of nested dependent type
//
name not in a base class list or
}
//
as a base class identifier in a
//
mem. init. list: typename required
};
這樣的矛盾很令人討厭,但是一旦你在經(jīng)歷中獲得一點(diǎn)經(jīng)驗(yàn),你幾乎不會(huì)在意它。
讓我們來(lái)看最后一個(gè) typename 的例子,因?yàn)樗谀憧吹降恼鎸?shí)代碼中具有代表性。假設(shè)我們?cè)趯?xiě)一個(gè)取得一個(gè) iterator(迭代器)的 function template(函數(shù)模板),而且我們要做一個(gè) iterator(迭代器)指向的 object(對(duì)象)的局部拷貝 temp,我們可以這樣做:
template
<
typename IterT
>
void
workWithIterator(IterT iter)
{
typename std::iterator_traits
<
IterT
>
::value_type temp(
*
iter);
}
不要讓 std::iterator_traits<IterT>::value_type 嚇倒你。那僅僅是一個(gè) standard traits class(標(biāo)準(zhǔn)特性類)的使用,用 C++ 的說(shuō)法就是 "the type of thing pointed to by objects of type IterT"(“被類型為 IterT 的對(duì)象所指向的東西的類型”)。這個(gè)語(yǔ)句聲明了一個(gè)與 IterT objects 所指向的東西類型相同的 local variable(局部變量)(temp),而且用 iter 所指向的 object(對(duì)象)對(duì) temp 進(jìn)行了初始化。如果 IterT 是 vector<int>::iterator,temp 就是 int 類型。如果 IterT 是 list<string>::iterator,temp 就是 string 類型。因?yàn)?std::iterator_traits<IterT>::value_type 是一個(gè) nested dependent type name(嵌套依賴類型名)(value_type 嵌套在 iterator_traits<IterT> 內(nèi)部,而且 IterT 是一個(gè) template parameter(模板參數(shù))),我們必須讓它被 typename 前置。
如果你覺(jué)得讀 std::iterator_traits<IterT>::value_type 令人討厭,就想象那個(gè)與它相同的東西來(lái)代表它。如果你像大多數(shù)程序員,對(duì)多次輸入它感到恐懼,那么你就需要?jiǎng)?chuàng)建一個(gè) typedef。對(duì)于像 value_type 這樣的 traits member names(特性成員名),一個(gè)通用的慣例是 typedef name 與 traits member name 相同,所以這樣的一個(gè) local typedef 通常定義成這樣:
template
<
typename IterT
>
void
workWithIterator(IterT iter)
{
typedef typename std::iterator_traits
<
IterT
>
::value_type value_type;
value_type temp(
*
iter);
}
很多程序員最初發(fā)現(xiàn) "typedef typename" 并列不太和諧,但它是涉及 nested dependent type names(嵌套依賴類型名)規(guī)則的一個(gè)合理的附帶結(jié)果。你會(huì)相當(dāng)快地習(xí)慣它。你畢竟有著強(qiáng)大的動(dòng)機(jī)。你輸入 typename std::iterator_traits<IterT>::value_type 需要多少時(shí)間?
作為結(jié)束語(yǔ),我應(yīng)該提及編譯器與編譯器之間對(duì)圍繞 typename 的規(guī)則的執(zhí)行情況的不同。一些編譯器接受必需 typename 時(shí)它卻缺失的代碼;一些編譯器接受不許 typename 時(shí)它卻存在的代碼;還有少數(shù)的(通常是老舊的)會(huì)拒絕 typename 出現(xiàn)在它必需出現(xiàn)的地方。這就意味著 typename 和 nested dependent type names(嵌套依賴類型名)的交互作用會(huì)導(dǎo)致一些輕微的可移植性問(wèn)題。
Things to Remember
·在聲明 template parameters(模板參數(shù))時(shí),class 和 typename 是可互換的。
·用 typename 去標(biāo)識(shí) nested dependent type names(嵌套依賴類型名),在 base class lists(基類列表)中或在一個(gè) member initialization list(成員初始化列表)中作為一個(gè) base class identifier(基類標(biāo)識(shí)符)時(shí)除外
posted on 2011-06-16 10:29
IT菜鳥(niǎo)
閱讀(108)
評(píng)論(0)
編輯
收藏
引用
只有注冊(cè)用戶
登錄
后才能發(fā)表評(píng)論。
【推薦】100%開(kāi)源!大型工業(yè)跨平臺(tái)軟件C++源碼提供,建模,組態(tài)!
網(wǎng)站導(dǎo)航:
博客園
IT新聞
BlogJava
博問(wèn)
Chat2DB
管理
Copyright @ IT菜鳥(niǎo)
Powered by:
.Text
and
ASP.NET
Theme by:
.NET Monster
久久久久亚洲精品无码蜜桃
|
久久91精品国产91
|
国内精品久久国产
|
2021久久精品免费观看
|
国产精品乱码久久久久久软件
|
精品精品国产自在久久高清
|
亚洲精品99久久久久中文字幕
|
中文字幕日本人妻久久久免费
|
久久久久女教师免费一区
|
成人国内精品久久久久一区
|
亚洲国产另类久久久精品黑人
|
日产精品久久久一区二区
|
99久久国产综合精品成人影院
|
久久久久亚洲AV综合波多野结衣
|
99久久免费国产精品特黄
|
一本大道久久香蕉成人网
|
伊人情人综合成人久久网小说
|
人妻精品久久久久中文字幕69
|
无码国内精品久久人妻
|
91精品国产91久久久久福利
|
99久久综合国产精品二区
|
伊人久久大香线蕉亚洲
|
国内精品人妻无码久久久影院
|
成人国内精品久久久久影院VR
|
性高湖久久久久久久久AAAAA
|
狠狠色婷婷久久一区二区三区
|
99久久综合狠狠综合久久止
|
国产成人精品久久免费动漫
|
亚洲国产精品久久
|
av国内精品久久久久影院
|
久久久久一本毛久久久
|
国内精品久久人妻互换
|
精品国产青草久久久久福利
|
日本加勒比久久精品
|
亚洲成色www久久网站夜月
|
精品久久久久久国产91
|
狠狠色丁香久久婷婷综合
|
久久这里只有精品久久
|
精品久久久久久中文字幕大豆网
|
久久免费视频网站
|
精品无码久久久久久国产
|