• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            #ant

            The dreams in which I'm dying are the best I've ever had...

            為什么不要特化函數(shù)模版

            Overloading vs. Specialization

            在C++中有class templatesfunction templates,這兩種模版有很多區(qū)別,最重要的區(qū)別就是重載(overloading):
            普通的C++類不能重載,當(dāng)然類模版也不能重載;相反,普通函數(shù)可以重載,函數(shù)模版也能重載。這再正常不過,看下面的代碼:

            ?1?// ?Example?1:?Class?vs.?function?template,?and?overloading?
            ?2?//

            ?3?
            ?4?//?A?class?template
            ?5?template<class?T>?class?X?{?/*...*/?};??????// ?(a)
            ?6?

            ?7?//?A?function?template?with?two?overloads
            ?8?template<class?T>?void?f(?T?);??????????????//?(b)
            ?9?template<class?T>?void?f(?int,?T,?double?);?// ?(c)
            10?

            像上面未特化的模板通常叫做base templates。當(dāng)然,base templates能夠被特化,在特化這一點(diǎn)上
            class templatesfunction templates有很大的區(qū)別:一個(gè)class template 能夠被partially specialized and/or
            fully specialized,一個(gè)function template只能被fully specialized,但是由于function templates能夠重載我們可以通過重載來實(shí)現(xiàn)和partially specialized 相當(dāng)?shù)墓δ堋O旅娴拇a說明了這些區(qū)別:

            ?1?// ?Example?1,?continued:?Specializing?templates?
            ?2?//

            ?3?
            ?4?//?A?partial?specialization?of?(a)?for?pointer?types?
            ?5?template<class?T>?class?X<T*>?{?/*...*/ ?};
            ?6?

            ?7?//?A?full?specialization?of?(a)?for?int?
            ?8?template<>?class?X<int>?{?/*...*/ ?};
            ?9?

            10?// ?A?separate?base?template?that?overloads?(b)?and?(c)?
            11?//
            ?--?NOT?a?partial?specialization?of?(b),?because?
            12?//
            ?there's?no?such?thing?as?a?partial?specialization?
            13?//?of?a?function?template!?

            14?template<class?T>?void?f(?T*?);?????????????// ?(d)
            15?

            16?//?A?full?specialization?of?(b)?for?int?
            17?template<>?void?f<int>(?int?);??????????????// ?(e)
            18?

            19?// ?A?plain?old?function?that?happens?to?overload?with?
            20?//
            ?(b),?(c),?and?(d)?--?but?not?(e),?which?we'll?
            21?//?discuss?in?a?moment?

            22?void?f(?double?);???????????????????????????// ?(f)
            23?

            根據(jù)函數(shù)重載解析規(guī)則:

            ?1?// ?Example?1,?continued:?Overload?resolution?
            ?2?//?

            ?3? bool?b;?
            ?4?int
            ?i;?
            ?5?double
            ?d;
            ?6?

            ?7?f(?b?);????????//?calls?(b)?with?T?=?bool?
            ?8?f(?i,?42,?d?);?//?calls?(c)?with?T?=?int?
            ?9?f(?&i?);???????//?calls?(d)?with?T?=?int?
            10?f(?i?);????????//?calls?(e)?
            11?f(?d?);????????//?calls?(f)

            上面說的這些其實(shí)都是很簡(jiǎn)單的情況,大多數(shù)人很容易就能明白,下面的才是容易讓人弄混的:

            1.考慮如下代碼:

            ?1?// ?Example?2:?Explicit?specialization?
            ?2?//?

            ?3?template<class?T>?//?(a)?a?base?template?
            ?4?void ?f(?T?);
            ?5?

            ?6?template<class?T>?//?(b)?a?second?base?template,?overloads?(a)?
            ?7?void?f(?T*?);?????// ?????(function?templates?can't?be?partially?
            ?8???????????????????//?????specialized;?they?overload?instead)

            ?9?
            10?template<>????????//?(c)?explicit?specialization?of?(b)?
            11?void?f<>(int* );
            12?

            13?//?...
            14?
            15?int?* p;?
            16?f(?p?);???????????//?calls?(c)

            最后一行的結(jié)果像大多數(shù)人所期望的一樣,問題是:為什么期望是這個(gè)結(jié)果?
            如果你期望的原因是錯(cuò)誤的,接下來的一定會(huì)讓你好奇。也許你會(huì)說:"我為int*寫了一個(gè)特化版本,f(p)當(dāng)然會(huì)調(diào)用c",不幸的是,這正是錯(cuò)誤的原因!!!

            2.再考慮下面的代碼:

            ?1?// ?Example?3
            ?2?//?

            ?3?template<class?T>?//?(a)?same?old?base?template?as?before?
            ?4?void ?f(?T?);
            ?5?

            ?6?template<>????????//?(c)?explicit?specialization,?this?time?of?(a)
            ?7?void?f<>(int* );
            ?8?

            ?9?template<class?T>?//?(b)?a?second?base?template,?overloads?(a)?
            10?void?f(?T* ?);
            11?

            12?//?...
            13?
            14?int?* p;?
            15?f(?p?);???????????//
            ?calls?(b)!?overload?resolution?ignores?
            16???????????????????//
            ?specializations?and?operates?on?the?base?
            17???????????????????//?function?templates?only

            如果這個(gè)結(jié)果讓你感到驚奇,那就對(duì)了!很多人都會(huì)感到驚奇!
            理解這個(gè)的關(guān)鍵是:Specializations don't overload,only the base templates overload.

            重載解析僅僅選擇base template(或者nontemplate function,如果有的話),只有當(dāng)編譯器已經(jīng)決定了哪個(gè)
            base template將會(huì)被選擇,編譯器才會(huì)繼續(xù)往下尋找適合的特化版本,如果找到了就使用那個(gè)特化版本。

            最后,應(yīng)當(dāng)避免特化函數(shù)模板,也要避免重載函數(shù)模板(nontemplate function的重載當(dāng)然沒問題)。如果一定要這樣,可以使用如下方法模擬函數(shù)模板的偏特化:

            ?1?//base?template?class,?
            ?2?template?<class?T>
            ?3? struct?FuncImpl?{
            ?4?????//users,?go?ahead?and?specialize?this

            ?5?????static?int?apply(const?T?& t)?{
            ?6?????????return?0
            ;
            ?7?
            ????}
            ?8?
            };
            ?9?

            10?//partial?specialazation?for?int
            11?template?<>
            12?struct?FuncImpl<int> ?{
            13?????static?int?apply(int
            ?t)?{
            14?????????return?1
            ;
            15?
            ????}
            16?
            };
            17?

            18?//partial?specialazation?for?T*
            19?template?<class?T>
            20?????struct?FuncImpl<T?*> ?{
            21?????static?int?apply(T?*
            t)?{
            22?????????return?2
            ;
            23?
            ????}
            24?
            };
            25?

            26?//users,?don't?touch?this!
            27?template?<class?T>
            28?int?func(const?T?& t)?{
            29?????return?FuncImpl<T>
            ::apply(t);
            30?
            }
            31?

            32?int?i?=?10 ,?r;
            33?r?=?func('c');?//r?=?0

            34?r?=?func(8);?//r?=?1
            35?r?=?func(&i);?//r?=?2

            posted on 2007-08-30 13:55 螞蟻終結(jié)者 閱讀(4183) 評(píng)論(4)  編輯 收藏 引用 所屬分類: C++

            Feedback

            # re: 為什么不要特化函數(shù)模版 2007-08-30 16:54 minidxer

            不錯(cuò)  回復(fù)  更多評(píng)論   

            # re: 為什么不要特化函數(shù)模版 2007-08-31 09:01 calmman

            不錯(cuò)!  回復(fù)  更多評(píng)論   

            # re: 為什么不要特化函數(shù)模版 2007-09-03 13:16 ymmol

            如果那個(gè)特化函數(shù)有交代清楚,那就沒那么多問題了:
            template<>
            void f<int>(int arg){
            //...
            }

            template<>
            void f<int *>(int *arg){
            //...
            }

            在調(diào)用時(shí)寫清楚也會(huì)少些疑惑:
            int ia=1;
            f<int>(ia);
            f<int *>(&ia);
            所以我覺得重載或特化都可以,只要你寫清楚了,都沒事  回復(fù)  更多評(píng)論   

            # re: 為什么不要特化函數(shù)模版 2007-09-03 17:08 螞蟻終結(jié)者

            @ymmol
            是啊,不過有像我這樣懶的程序員,習(xí)慣了將參數(shù)推導(dǎo)交給編譯器,也習(xí)慣了make_pair類似的寫法。  回復(fù)  更多評(píng)論   

            日韩久久久久中文字幕人妻| 久久久久99精品成人片直播| 国产AV影片久久久久久| 国产91久久综合| 2021国产精品久久精品| 亚洲国产精品久久久久久| 欧美性猛交xxxx免费看久久久| 亚洲狠狠婷婷综合久久久久| 国产毛片久久久久久国产毛片| 亚洲人成伊人成综合网久久久| 国产精品gz久久久| 久久久久亚洲AV无码麻豆| 久久久久人妻一区精品| 成人资源影音先锋久久资源网| 一级a性色生活片久久无少妇一级婬片免费放| 精品久久久无码21p发布| 久久国产精品免费| 99国产精品久久久久久久成人热| 久久国产色av免费看| 精品伊人久久久| 久久久久亚洲AV无码去区首| 久久久久免费精品国产| 国产精品久久久久久| 精品久久久久久亚洲精品 | 老司机午夜网站国内精品久久久久久久久| 欧美黑人又粗又大久久久 | 久久久精品人妻一区二区三区蜜桃| 国产精品免费久久久久影院 | 久久久无码精品亚洲日韩按摩| 久久精品18| 久久久久久久亚洲精品| 国产亚洲婷婷香蕉久久精品| 嫩草影院久久国产精品| 久久发布国产伦子伦精品| 亚洲AV无码久久| 久久久老熟女一区二区三区| 亚洲中文字幕无码久久2017| 国内精品九九久久精品 | av午夜福利一片免费看久久| 久久美女网站免费| 91麻精品国产91久久久久|