青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

我們知道在C++模板編程中如果我們特化或是偏特化某個(gè)模板類, 我們需要重寫(xiě)整個(gè)模板類中的所有函數(shù), 但是這些代碼通常是非常相似的, 甚至在某些情況下可能只有一兩個(gè)函數(shù)會(huì)不一樣,其他函數(shù)都是一樣的。在這種情況下,同時(shí)存在多份相同的代碼,對(duì)我們維護(hù)這些代碼是非常不利的, 我們最好只需要特化其中不一樣的那個(gè)函數(shù)。

比如下面這個(gè)模板類:

 

template<typename T, unsigned B>
struct Base
{
    //other function
    //....
    void Func(){ cout << "primary function" << endl; }
};
void test1()
{
    Base<int1> a;
    a.Func();
    Base<int16> b;
    b.Func();
}
int main()
{
     test1();
}

 

 

只有當(dāng)B等于16時(shí), Func這個(gè)函數(shù)需要特化, 但是其他函數(shù)無(wú)論什么情況下都是一樣的。

下面是我們的一些可能解決方案:

方法1:

 

template<typename T>
struct Base<T, 16>
{
    //other function
    //....
    void Func(){ cout << "specialization function" << endl; }
};

 

點(diǎn)評(píng):通過(guò)偏特化實(shí)現(xiàn),需要重寫(xiě)所有的類成員方法。

 

方法2:

 

template<typename T, unsigned B>
struct Base
{
    //other function
    //....
    void Func()
    {
        if(B == 16)
        {
            cout << "primary function" << endl;
        }
        else
        {
            cout << "specialization function" << endl;
        }
    }
};

 

點(diǎn)評(píng): 通過(guò)運(yùn)行時(shí)判斷, 容易理解,但是相對(duì)低效。

 

方法3:

 

template<typename T, unsigned B>
struct Base
{
    //other function
    //....
    void Func()
    {
#if B!=16
            cout << "primary function" << endl;
#else
            cout << "specialization function" << endl;
#endif
    }
};

 

點(diǎn)評(píng): 試圖通過(guò)預(yù)編譯來(lái)實(shí)現(xiàn),但是這個(gè)方法是錯(cuò)誤的。C++模板編譯包括預(yù)編譯,語(yǔ)法檢查,模板實(shí)例化等階段,在預(yù)編譯階段模板參數(shù)都還沒(méi)有實(shí)例化呢。

 

方法4:

 

template<typename T, unsigned B>
struct Base
{
    //other function
    //....
    template<unsigned S>
    struct FuncObj
    {
        void operator()()
        {
            cout<<"primary function"<<endl;
        }
    };
    template<>
    struct FuncObj<16>
    {
        void operator()()
        {
            cout<<"specialization function"<<endl;
        }
    };
    FuncObj<B> Func;
};

 

點(diǎn)評(píng): 通過(guò)成員類以防函數(shù)的形式特化, 增加了類成員變量。

 

方法5:

 

template<typename T, unsigned B>
struct Base
{
    //other function
    //....
    template<unsigned N>
    void FuncImpl()
    {
        cout<<"primary function"<<endl;
    }
    template<>
    void FuncImpl<16>()
    {
        cout<<"specialization function"<<endl;
    }
    void Func()
    {
        FuncImpl<B>();
    }
};

 

點(diǎn)評(píng):通過(guò)類成員模板函數(shù)特化來(lái)實(shí)現(xiàn)。

 

方法6:

 

template<typename T, unsigned B>
struct Base
{
    //other function
    //....
    template<unsigned N> 
    class Int2Type
    {
        enum { value = N };
    };
    template<unsigned V>
    void FuncImpl(const Int2Type<V>)
    {
        cout<<"primary function"<<endl;
    }
    void FuncImpl(const Int2Type<16>)
    {
        cout<<"specialization function"<<endl;
    }
    void Func()
    {
        FuncImpl(Int2Type<B>());
    }
};

 

點(diǎn)評(píng): 通過(guò)將int根據(jù)值的不同轉(zhuǎn)成不同的類型,然后通過(guò)函數(shù)重載實(shí)現(xiàn)。

 

方法7:

 

namespace
{
    template <bool,typename T,typename> struct conditional { typedef T type; };
    template <typename T,typename U> struct conditional<false,T,U> {typedef U type; };
}
template<class T, unsigned B>
struct Base
{
    //other function
    //....

    void Func ()
    {
        typedef typename ::conditional<B!=16,primary_t,spec_t>::type type;
        Func_impl(type());
    }
private:
    struct primary_t { };
    struct spec_t    { };
    void Func_impl (primary_t) { std::cout << "primary function" << std::endl; }
    void Func_impl (spec_t   ) { std::cout << "specialization function" << std::endl; }
};

 

點(diǎn)評(píng): 和方法6類似,通過(guò)函數(shù)重載實(shí)現(xiàn)

 

方法8:

 namespace

 {
    template <bool,typename T = voidstruct enable_if { typedef T type; };
    template <typename T> struct enable_if<true,T> {};
}
template<class T, unsigned B>
struct Base
{
    //other function
    //....

    template <unsigned N>
    typename ::enable_if<16!=N>::type
        FuncImpl () { std::cout << "primary function" << std::endl; }
    template <unsigned N>
    typename ::enable_if<16==N>::type
        FuncImpl () { std::cout << "specialization function" << std::endl; }
    void Func() {
        FuncImpl<B>();
    }
};

點(diǎn)評(píng):通過(guò)enable_if, 利用SFINAE實(shí)現(xiàn)。

 

我們可以看到根據(jù)編譯時(shí)模板參數(shù)int值的不同,我們重寫(xiě)模板類的某個(gè)成員函數(shù)的方法是多種多樣的。針對(duì)上面這種情況,個(gè)人其實(shí)最推薦方法2,我們沒(méi)必要把簡(jiǎn)單的問(wèn)題復(fù)雜化。

 

下面我們考慮另外一個(gè)需求, 當(dāng)模板類的某個(gè)參數(shù)是某種類型時(shí), 我們要求特化其中的一個(gè)成員函數(shù):

 

template<typename T1, typename T2>
struct Base
{
    //other function
    //....
    void Func(){ cout << "primary function" << endl; }
};
void test2()
{
    Base<intint> a;
    a.Func();
    Base<intstring> b;
    b.Func();
}
int main()
{
    test2();
}

 

要求上面的模板類如果T2 是string類型, 我們要求對(duì)Func特殊重寫(xiě),其他的成員函數(shù)無(wú)論什么情況實(shí)現(xiàn)都是一樣的。

有了上面的那個(gè)例子的實(shí)現(xiàn)經(jīng)驗(yàn), 對(duì)這個(gè)問(wèn)題我們解決就方便多了。

 

方法1:

 

template<typename T1, typename T2>
struct Base
{
    //other function
    //....
    void Func()
    {
        if(typeid(std::string) == typeid(T2))
        {
            cout<<"specialization function"<<endl;
        }
        else
        {
            cout << "primary function" << endl; 
        }
    }
};

 

點(diǎn)評(píng):通過(guò)運(yùn)行時(shí)類型識(shí)別(RTTI)實(shí)現(xiàn),需要打開(kāi)相關(guān)編譯選項(xiàng),并且低效。

 

方法2:

 

template<typename T1, typename T2>
struct Base
{
    //other function
    //....
    template<typename T>
    void FuncImpl()
    {
        cout << "primary function" << endl; 
    }
    template<>
    void FuncImpl<string>()
    {
        cout << "specialization function" << endl; 
    }
    void Func()
    {
        FuncImpl<T2>();
    }
};

 

點(diǎn)評(píng):通過(guò)成員函數(shù)特化實(shí)現(xiàn)

 

方法3:

 

template<typename T1, typename T2>
struct Base
{
    //other function
    //....
    template<typename T> 
    class Type2Type
    {
        typedef T type;
    };
    template<typename T>
    void FunImpl(const Type2Type<T>)
    {
        cout << "primary function" << endl; 
    }
    template<typename T>
    void FunImpl(const Type2Type<string>)
    {
        cout << "specialization function" << endl; 
    }
    void Func()
    {
        FunImpl<T2>(Type2Type<T2>());
    }
};

 

點(diǎn)評(píng): 通過(guò)函數(shù)重載實(shí)現(xiàn)

 

方法4:

 

template<typename T>
struct IsString
{
    enum { value = false };
};
template<>
struct IsString<string>
{
    enum { value = true };
};
template<typename T1, typename T2>
struct Base
{
    //other function
    //....
    void Func()
    { 
        if(IsString<T2>::value)
        {
            cout << "specialization function" << endl; 
        }
        else
        {
            cout << "primary function" << endl; 
        }
    }
};

 

點(diǎn)評(píng): 通過(guò)編譯時(shí)類型判斷實(shí)現(xiàn)。

 

方法5:

 

template<typename T3,  typename T4>
struct must_be_same_type
{
    enum { ret = 0 };
};
template<>
struct must_be_same_type<stringstring>
{
    enum { ret = 1 };
};
template < typename T1,typename T2 >
class Base{
public:
    //other function
    //....
    void Func(){
        if(must_be_same_type<T2, string>::ret)
        {
            cout << "specialization function" << endl; 
        }
        else
        {
            cout << "primary function" << endl; 
        }
    }
};

 

點(diǎn)評(píng): 和方法4類似, 是不過(guò)實(shí)現(xiàn)方式不一樣。

 

最后,探討下我自己遇到的問(wèn)題, 我們?cè)趯?xiě)一個(gè)事件委托(delegate)類,大概如下:

 

template<typename return_type, typename first_type, typename second_type>
class CEvent 
{
public:
    //other function
    //....
    return_type operator()(first_type p1, second_type p2)
    {
        return_type ret = return_type();
        //...
        //ret = invoker(p1, p2);
        return ret;
    }
};
void test3()
{
    CEvent<intintint> e1;
    e1(12);
    CEvent<voidintint> e2;
    e2(12);
}
int main()
{
    test3();
}

 

我們可以看到,當(dāng)return_type是void時(shí), 因?yàn)闆](méi)有返回值,上面的代碼會(huì)編譯失敗,因此我們只能偏特化這種情況:

 

template<typename first_type, typename second_type>
class CEvent<void, first_type, second_type>
{
public:
    //other function
    //....
    void operator()(first_type p1, second_type p2)
    {
        //...
        //invoker(p1, p2);
        return;
    }
};

 

但是,我們會(huì)發(fā)現(xiàn)只有這個(gè)operator()函數(shù)是需要根據(jù)return_type特殊對(duì)待的,其他函數(shù)永遠(yuǎn)都是一樣的。

我們現(xiàn)在的問(wèn)題就是如何只特化這個(gè)函數(shù)。

 

首先我們會(huì)想到如下的實(shí)現(xiàn)方法:

 

template<typename T>
struct IsVoid
{
    enum { value = false };
};
template<>
struct IsVoid<void>
{
    enum { value = true };
};
template<typename return_type, typename first_type, typename second_type>
class CEvent 
{
public:
    other function
    ....
    return_type operator()(first_type p1, second_type p2)
    {
        if(IsVoid<return_type>::value)
        {
            cout << "return type is void" << endl;
            //...
            //invoker(p1, p2);
        }
        else
        {
            cout << "return type is not void" << endl;
            return_type ret = return_type();
            //...
            //ret = invoker(p1, p2);
            return ret;
        }
    }
};

 

但是我們很快會(huì)發(fā)現(xiàn)這種情況下if語(yǔ)句被編譯進(jìn)去了, 所以return_type是void的情況下還是會(huì)編譯失敗。

我們要解決的問(wèn)題就是如何把這個(gè)if語(yǔ)句變成函數(shù)重載,于是我們想到如下實(shí)現(xiàn):

 

template<typename T>
struct IsVoid
{
    enum { value = false };
};
template<>
struct IsVoid<void>
{
    enum { value = true };
};
template<int v>
class Int2Type
{
    enum {value = v };
};
template<typename return_type, typename first_type, typename second_type>
class CEvent 
{
public:
    //other function
    //....
    return_type InvokerImpl(first_type p1, second_type p2, Int2Type<true>)
    {
        cout << "return type is void" << endl;
        //...
        //invoker(p1, p2);
    }
    return_type InvokerImpl(first_type p1, second_type p2, Int2Type<false>)
    {
        cout << "return type is not void" << endl;
        return_type ret = return_type();
        //...
        //ret = invoker(p1, p2);
        return ret;
    }
    return_type operator()(first_type p1, second_type p2)
    {
        return InvokerImpl(p1, p2, Int2Type<IsVoid<return_type>::value>());
    }
};

 

上面的實(shí)現(xiàn)首先通過(guò)編譯時(shí)類型識(shí)別,然后再把識(shí)別后相應(yīng)的bool值轉(zhuǎn)成不同類型, 最后再利用不同類型函數(shù)重載實(shí)現(xiàn)。

 

最后總結(jié)下,我們可以看到,從編譯時(shí)到運(yùn)行時(shí),從面向?qū)ο蟮狡胀ǚ盒途幊淘俚侥0逶幊蹋珻++復(fù)雜得讓人無(wú)語(yǔ), 也強(qiáng)大得讓人無(wú)語(yǔ), 而且C++語(yǔ)言本身是在不斷發(fā)展的(C++11), 同一問(wèn)題在C++中往往有多種解決方案,這些解決方案有的簡(jiǎn)單,有的復(fù)雜,有的高效, 也有的低效, 而我們的目標(biāo)就是利用C++這把利器尋找簡(jiǎn)單而高效的解決方案。

 

注:本人初學(xué)C++ templates編程,如有錯(cuò)誤,歡迎指正。

      參考資料:http://bbs.csdn.net/topics/390116038

                    http://bbs.csdn.net/topics/270041821

posted on 2013-02-14 20:31 Richard Wei 閱讀(5422) 評(píng)論(10)  編輯 收藏 引用 所屬分類: STL&GP

FeedBack:
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-14 21:19 | lwch
Orz.....  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-14 21:31 | Richard Wei
@lwch
不懂, 什么意思?
不過(guò)看了你的博客,學(xué)習(xí)了 ^_^   回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-15 20:36 | lwch
@Richard Wei
膜拜ing.....  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-15 20:41 | Richard Wei
@lwch
慚愧, 雖然工作好多年,最近才開(kāi)始研究模板,準(zhǔn)備稍微深入一下。  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-19 08:42 | 歲月漫步
真的沒(méi)看明白什么意思  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-19 09:01 | Richard Wei
@歲月漫步
那就看看這個(gè)http://bbs.csdn.net/topics/390116038  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-22 09:34 | 永遇樂(lè)
又讓我在這里復(fù)習(xí)了一下SFINAE,謝謝  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-23 08:28 | a_very_big_graywolf
樓主真蛋疼,精神值得學(xué)習(xí)。
只想說(shuō)一句,兩個(gè)需求可以用一個(gè)更簡(jiǎn)單的辦法來(lái)解決:
調(diào)整程序設(shè)計(jì),用繼承來(lái)規(guī)避只特化某個(gè)成員函數(shù)的方法。
這樣就用繼承的優(yōu)勢(shì)來(lái)減少代碼重復(fù)量了。
僅供參考  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-02-23 16:28 | Richard Wei
@a_very_big_graywolf
只是總結(jié), 以后再用到會(huì)方便一些。
不錯(cuò), 前2個(gè)需求也可以用繼承來(lái)實(shí)現(xiàn), 但是如果該特化函數(shù)基類內(nèi)部有調(diào)用,就可能要搞成虛函數(shù)了。  回復(fù)  更多評(píng)論
  
# re: 在C++范型編程中如何只特化類的一個(gè)成員函數(shù)
2013-03-04 16:22 | tb
膜拜ing..... 太強(qiáng)了   回復(fù)  更多評(píng)論
  

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品自拍网站| 免费短视频成人日韩| 亚洲国产日韩在线| 欧美一区二区三区视频在线观看| 欧美日韩国产大片| 亚洲国产日韩一区| 久久免费99精品久久久久久| 亚洲一区二区黄| 欧美日韩精品免费观看视频| 亚洲第一区在线观看| 久久精品国语| 亚洲欧美一区二区三区在线| 国产精品video| 一区二区三区高清在线观看| 亚洲春色另类小说| 久久亚洲欧美| 黄色日韩网站| 久久裸体视频| 欧美一级视频一区二区| 国产精品三区www17con| 亚洲免费网址| 在线中文字幕一区| 欧美性视频网站| 亚洲少妇在线| 日韩午夜激情| 欧美日韩免费一区二区三区视频 | 亚洲欧美国产毛片在线| 亚洲精品美女在线| 欧美极品一区| 一区二区三区精品久久久| 亚洲国语精品自产拍在线观看| 狼狼综合久久久久综合网| 揄拍成人国产精品视频| 麻豆91精品| 久久全国免费视频| 亚洲二区在线| 欧美激情影音先锋| 欧美电影免费| 一区二区高清在线| 一区二区福利| 国产精品一区久久久久| 久久精品国产999大香线蕉| 欧美在线视频观看| 伊人夜夜躁av伊人久久| 女人色偷偷aa久久天堂| 欧美成人一区二区在线| 日韩一级欧洲| 一区二区不卡在线视频 午夜欧美不卡在 | 欧美中文字幕第一页| 国产午夜久久久久| 美国十次了思思久久精品导航| 久久青草欧美一区二区三区| 亚洲欧洲精品一区二区| 亚洲精品欧美| 国产精品第一区| 久久成人羞羞网站| 久久久久国产精品一区三寸 | 国产精品hd| 久久大逼视频| 久久久综合视频| 9l视频自拍蝌蚪9l视频成人| 一区二区三区日韩精品| 国产日韩欧美不卡在线| 另类激情亚洲| 欧美日韩福利视频| 欧美永久精品| 美女图片一区二区| 亚洲视频精品| 欧美在线日韩精品| 亚洲三级影院| 亚洲一区免费视频| 亚洲大片一区二区三区| 亚洲人成小说网站色在线| 国产精品视频久久一区| 欧美高清一区二区| 欧美性事免费在线观看| 久久综合成人精品亚洲另类欧美| 欧美jizz19性欧美| 性欧美办公室18xxxxhd| 久久伊人免费视频| 亚洲深爱激情| 久久久久国产精品厨房| 中日韩美女免费视频网站在线观看| 亚洲影视中文字幕| 亚洲欧洲日韩在线| 亚洲——在线| 亚洲精品123区| 亚洲综合首页| 亚洲乱码国产乱码精品精可以看| 亚洲欧美日韩一区二区| 亚洲精品无人区| 翔田千里一区二区| 一本大道久久a久久精品综合| 欧美在线免费| 亚洲午夜久久久| 久久久综合精品| 午夜视频在线观看一区| 欧美成人午夜| 久久精品二区| 欧美图区在线视频| 免费永久网站黄欧美| 国产精品欧美久久久久无广告| 欧美成黄导航| 国产日韩欧美麻豆| 99精品视频免费全部在线| 在线观看日产精品| 亚洲欧美国产高清va在线播| 日韩午夜高潮| 久久资源av| 久久精品一区二区国产| 欧美午夜性色大片在线观看| 欧美第一黄网免费网站| 国产日韩欧美二区| 日韩午夜在线播放| 亚洲欧洲一区二区三区在线观看| 欧美一区二区在线观看| 亚洲综合色在线| 欧美精品1区2区| 免费不卡亚洲欧美| 国产一区日韩一区| 亚洲综合精品四区| 亚洲图片欧洲图片av| 欧美激情亚洲激情| 欧美激情在线| 亚洲电影自拍| 久久久久www| 久久久久久综合| 国产精品一级在线| 亚洲午夜av电影| 亚洲综合首页| 欧美日韩视频不卡| 亚洲人成人一区二区在线观看| 亚洲国产精品久久久久秋霞蜜臀 | 久久久噜噜噜久久人人看| 国产精品一区二区三区免费观看 | 国产精品成人在线观看| 亚洲人成网站精品片在线观看| 亚洲黄色精品| 蜜桃精品一区二区三区| 免费久久99精品国产自在现线| 国产在线不卡视频| 性色一区二区| 久久精品国产精品亚洲综合| 国产欧美 在线欧美| 亚洲欧美综合v| 欧美亚洲在线视频| 国产精品尤物福利片在线观看| 亚洲视频你懂的| 亚洲欧美日本国产专区一区| 国产精品h在线观看| 亚洲私人黄色宅男| 欧美一区二区精品久久911| 国产精品午夜电影| 午夜精品成人在线| 久久精品日产第一区二区| 国产一区二区三区四区| 欧美影片第一页| 媚黑女一区二区| 91久久国产综合久久| 欧美激情第二页| 亚洲理伦在线| 亚洲一区美女视频在线观看免费| 欧美午夜一区二区| 亚洲专区一区| 久久久久久久久久久成人| 伊人久久亚洲影院| 嫩草国产精品入口| 亚洲精品久久久久久一区二区| 这里只有精品在线播放| 国产精品成人观看视频国产奇米| 亚洲一区二区伦理| 久久久久久久久久看片| 在线免费观看日本一区| 欧美大片18| 在线一区二区三区做爰视频网站| 欧美在线观看天堂一区二区三区| 国内精品模特av私拍在线观看| 久久综合久久综合九色| 亚洲激情综合| 性欧美8khd高清极品| 精品二区视频| 欧美另类女人| 亚洲欧美日韩一区二区在线| 狂野欧美激情性xxxx| 99精品国产高清一区二区| 国产精品久久久久影院色老大| 久久动漫亚洲| 亚洲精品影视| 久久国产精品久久久| 亚洲国产精品一区二区久| 欧美日韩精品免费在线观看视频| 亚洲尤物在线| 欧美大片免费久久精品三p| 亚洲视频一二| 狠狠色丁香久久综合频道| 欧美精品一区三区| 欧美亚洲视频| 亚洲人成在线观看网站高清| 欧美怡红院视频| 亚洲日本免费|