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

qiezi的學習園地

AS/C/C++/D/Java/JS/Python/Ruby

  C++博客 :: 首頁 :: 新隨筆 ::  ::  :: 管理 ::

說明:
要看懂后面那部分代碼,即使用Typelist的部分,最好預先看過《C++設計新思維》,英文版名為《Modern C++ Design》。
If模板類在寫完后想起來好像在哪見過,早晨去公司查閱了一下,在《產生式編程——方法、工具與應用》一書中有講,英文名為《Generative Programming -- Methods, Tools, and Applications》基本和本篇中一個樣。


前2篇亂七八糟地講了一些,有一個遺留問題,函數原型的推導。

簡要描述如下:

Method < void(in<int>in<char>, inout<string>out<short>> method;

// 同步調用
string str = "hello";
short value = 2;
method (
3'a', str, value);

// 異步調用1
method.async_call (3'a'"hello");

// 異步調用2
void test_func (intcharstringshort);
method.async_call (
3'a'"hello", test_func);


要產生這3種函數形式。參數類型如何轉換,是以后的話題,本篇主要解決異步調用的函數原形推導問題。本篇也不討論Method的模板參數(即那個函數類型)返回類型不為void的情況。

第一種形式,同步調用,比較好處理,參數個數和模板參數的數量相同。

后2種形式,如何讓編譯器根據in/out來推導出函數原型?

我們需要編譯器做這樣的處理,async_call的參數類型中,in類型的參數將保留,out類型的參數不需要,inout類型也需要保留。

要用到的Loki頭文件:

#include <static_check.h>
#include 
<Typelist.h>

using namespace Loki;
using namespace Loki::TL;


首先看看in/inout/out的聲明。為了簡化,這里去掉了跟類型推導無關的部分。

class NullType
{
    NullType ();
};

template 
<class T>
struct in
{
    typedef T OriginalType;
};

template 
<class T>
struct out
{
    typedef T OriginalType;
};

template 
<class T>
struct inout
{
    typedef T OriginalType;
};

下面Method模板類的聲明,使用偏特化來產生代碼。為了簡化,我只取函數參數個數為4個參數的版本,比照著上面的代碼來解釋,只解釋method.async_call (3, 'a', "hello", test_func);這個版本,因為另一個比它簡單。

template <class T>
struct Method
{
};

template 
<class Ret, class A, class B, class C, class D>
struct Method <Ret(A,B,C,D)> 
{
};


根據上面Method的定義,Method < void(in, in, inout, out) > ,async_call函數的類型將是:

typedef void (*FUNC_TYPE)(intcharstringshort);
void async_call (intcharstring, FUNC_TYPE func);

實際上FUNC_TYPE應該能夠接受更廣泛的類型,比如void(int, char, char*, short),這可以在內部做一些轉換,不過本篇的重點不在這里,所以只講上面的那種形式。

直接在Method類中實現有些麻煩,所以我把這個函數放在一個基類中實現,只要編譯器能幫我們推導出下面這種形式就行了:

template <class Ret, class A, class B, class C, class D>
struct Method <Ret(A,B,C,D)> : public Base < A, B, C >
{
};


注意,這里是以Method < void(in, in, inout, out) >這種形式來講的,才會有上面那種繼承關系。而實際上,由于in/out在參數中的位置、數量都是未知的,要到定義時才能確定,所以使用模板來推導。(入正題了)

也就是說,只要我們能使用靜態推導方式,獲得A,B,C,D這四個參數中所有的in類型,把它交給Base作為模板參數就成了。

這里需要一個輔助的模板類,用來在編譯時幫助推導:

template <class T>
class InOutTypeTraits
{
    Loki::CompileTimeError 
<false> Not_Supported_Type;
};

template 
<class T>
struct InOutTypeTraits < in<T> >
{
    
enum {isin=1, isout=0};
};

template 
<class T>
struct InOutTypeTraits < out<T> >
{
    
enum {isin=0, isout=1};
};

template 
<class T>
struct InOutTypeTraits < inout<T> >
{
    
enum {isin=1, isout=1};
};

template 
<>
struct InOutTypeTraits < NullType >
{
    
enum {isin=0, isout=0};
};

通過另一個模板類InList來幫我們產生所有的in類型,它的結果是一個Typelist。為了方便以后使用,我把out類型產生器也做了一個OutList。

template <int CONDITION, class _IF, class _ELSE>
struct If
{
    typedef _IF Result;
};

template 
<class _IF, class _ELSE>
struct If <0, _IF, _ELSE>
{
    typedef _ELSE Result;
};

template 
<class A = NullType, class B = NullType, class C = NullType, class D = NullType, 
    
class E = NullType, class F = NullType, class G = NullType, class H = NullType
>
struct InList
{
    typedef typename If 
< 
        InOutTypeTraits 
<A>::isin,
        typename Typelist 
< A, typename InList<B,C,D,E,F,G>::Result >
        typename InList
<B,C,D,E,F,G,H>::Result 
    
>::Result Result;
};

template 
<class A>
struct InList <A, NullType, NullType, NullType, NullType, NullType, NullType, NullType>
{
    typedef typename If 
<
        InOutTypeTraits 
<A>::isin,
        typename MakeTypelist 
<A>::Result,
        typename MakeTypelist 
<>::Result
    
>::Result Result;
};

template 
<class A = NullType, class B = NullType, class C = NullType, class D = NullType, 
    
class E = NullType, class F = NullType, class G = NullType, class H = NullType
>
struct OutList
{
    typedef typename If 
< 
        InOutTypeTraits
<A>::isout,
        typename Typelist 
< A, typename OutList<B,C,D,E,F,G>::Result >
        typename OutList
<B,C,D,E,F,G,H>::Result 
    
>::Result Result;
};

template 
<class A>
struct OutList <A, NullType, NullType, NullType, NullType, NullType, NullType, NullType>
{
    typedef typename MakeTypelist 
<A>::Result Result;
};

它的原理是,根據If模板類來判斷一個類型是不是in類型,是的話就把它加入到Typelist中,不是就排除它。

InList , in, inout, out::Result是一個Typelist , Typelist, Typelist, NullType> > >類型,說簡單點,它和MakeTypelist < in, in, inout >::Result是等價的。

現在Base模板類將接受一個模板參數,它是一個Typelist類型,這個不詳細講了,把它的定義寫出來:

template <class T, int T_COUNT = Length <IN_TYPE>::value >
struct Base
{
    Loki::CompileTimeError 
<false> Only_Use_Partial_Specialisation_Version;
};

template 
<class T>
struct Base <T, 0>
{
    typedef 
void(*FUNC_TYPE)();

    template 
<class FUNC_TYPE>
    
void async_call (FUNC_TYPE func)
    {
    }
    
void async_call ()
    {
    }
};

template 
<class T>
struct Base <T, 1>
{
    typedef 
void(*FUNC_TYPE)(
        typename TypeAt 
<T, 0>::Result::OriginalType);

    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0,
        FUNC_TYPE func)
    {
    }
    
void async_call (typename TypeAt <T, 0>::Result::OriginalType v0)
    {
    }
};

template 
<class T>
struct Base <T, 2>
{
    typedef 
void(*FUNC_TYPE)(
        typename TypeAt 
<T, 0>::Result::OriginalType,
        typename TypeAt 
<T, 1>::Result::OriginalType);

    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0, 
        typename TypeAt 
<T, 1>::Result::OriginalType v1, 
        FUNC_TYPE func)
    {
    }
    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0, 
        typename TypeAt 
<T, 1>::Result::OriginalType v1)
    {
    }
};

template 
<class T>
struct Base <T, 3>
{
    typedef 
void(*FUNC_TYPE)(
        typename TypeAt 
<T, 0>::Result::OriginalType, 
        typename TypeAt 
<T, 1>::Result::OriginalType,
        typename TypeAt 
<T, 2>::Result::OriginalType);

    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0, 
        typename TypeAt 
<T, 1>::Result::OriginalType v1, 
        typename TypeAt 
<T, 2>::Result::OriginalType v2, 
        FUNC_TYPE func)
    {
    }
    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0,
        typename TypeAt 
<T, 1>::Result::OriginalType v1,
        typename TypeAt 
<T, 2>::Result::OriginalType v2)
    {
    }
};

template 
<class T>
struct Base <T, 4>
{
    typedef 
void(*FUNC_TYPE)(
        typename TypeAt 
<T, 0>::Result::OriginalType, 
        typename TypeAt 
<T, 1>::Result::OriginalType,
        typename TypeAt 
<T, 2>::Result::OriginalType,
        typename TypeAt 
<T, 3>::Result::OriginalType);

    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0, 
        typename TypeAt 
<T, 1>::Result::OriginalType v1, 
        typename TypeAt 
<T, 2>::Result::OriginalType v2, 
        typename TypeAt 
<T, 3>::Result::OriginalType v3,
        FUNC_TYPE func)
    {
    }
    
void async_call (
        typename TypeAt 
<T, 0>::Result::OriginalType v0,
        typename TypeAt 
<T, 1>::Result::OriginalType v1,
        typename TypeAt 
<T, 2>::Result::OriginalType v2,
        typename TypeAt 
<T, 3>::Result::OriginalType v3)
    {
    }
};

這部分有點多,其實還是比較清晰的。注意這個Base的版本已經不是上面所講的那個了。

函數原形推導問題就講完了。上面的代碼不一定還能編譯,昨天是能編譯的,被我修改了一些,為了解釋,又改成昨天那樣子。
posted on 2005-09-20 22:34 qiezi 閱讀(621) 評論(6)  編輯 收藏 引用 所屬分類: 自家破爛C++asgard項目
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲天堂成人| 欧美在线观看视频在线| 国产精品拍天天在线| 欧美精品一区二区三区在线看午夜| 久久久久久久精| 免费黄网站欧美| 欧美在线观看www| 国产精品一区二区三区乱码| 国产精品二区三区四区| 国产精品蜜臀在线观看| 国产午夜精品视频| 亚洲免费av网站| 亚洲欧美综合v| 欧美wwwwww| 一区二区三区四区五区视频| 亚洲永久精品大片| 美女国产一区| 国产精品高潮呻吟久久| 激情一区二区三区| 99国内精品久久| 欧美中日韩免费视频| 亚洲高清在线观看| 国产精品99久久久久久www| 久久精品在线播放| 欧美调教vk| 91久久精品一区二区别| 午夜伦理片一区| 亚洲欧洲精品一区二区三区波多野1战4| 在线视频一区二区| 美女国产一区| 国内揄拍国内精品久久| 亚洲一区在线播放| 欧美激情成人在线视频| 欧美一级淫片播放口| 欧美日韩一区二区三区在线看| 国产一区二区三区黄视频| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 欧美在线视频日韩| 欧美日韩国产系列| 在线观看av一区| 欧美影院精品一区| 亚洲尤物在线| 国产精品福利影院| 亚洲无亚洲人成网站77777| 欧美激情精品久久久久久久变态| 午夜精品久久久久久久99樱桃| 欧美人与性动交cc0o| 亚洲欧洲日本mm| 欧美成人午夜剧场免费观看| 久久福利一区| 国内偷自视频区视频综合| 欧美亚洲综合久久| 亚洲综合电影| 国产日产亚洲精品| 久久久.com| 久久狠狠久久综合桃花| 国外成人在线视频| 欧美电影打屁股sp| 欧美成人在线免费视频| 亚洲香蕉视频| 久久五月激情| 欧美一区网站| 一区二区在线视频| 免费欧美日韩| 六月婷婷久久| 亚洲精品美女91| 亚洲人成在线播放网站岛国| 欧美成人午夜免费视在线看片| 亚洲国产另类 国产精品国产免费| 蜜臀91精品一区二区三区| 美女诱惑一区| 亚洲视频中文字幕| 西瓜成人精品人成网站| 激情综合久久| 亚洲精品在线观| 国产精品日韩欧美一区| 久久麻豆一区二区| 欧美va亚洲va国产综合| 宅男66日本亚洲欧美视频| 亚洲亚洲精品三区日韩精品在线视频 | 亚洲精品久久久久久一区二区| 免费人成精品欧美精品| 亚洲免费电影在线观看| 一区二区免费在线播放| 国模私拍视频一区| 亚洲黄色av| 国产精品社区| 欧美韩日精品| 国产精品一二| 欧美国产日本在线| 国产精品视频九色porn| 欧美成人黄色小视频| 国产精品成人午夜| 欧美成人蜜桃| 国产嫩草一区二区三区在线观看| 欧美va亚洲va国产综合| 国产精品毛片a∨一区二区三区|国| 久久中文久久字幕| 国产精品家教| 亚洲国内精品在线| 国外精品视频| 亚洲一区二区精品在线| 亚洲精品久久视频| 欧美在线播放高清精品| 亚洲视频在线观看免费| 另类天堂av| 久久久噜噜噜久久人人看| 欧美日韩在线另类| 亚洲国内自拍| 亚洲激情欧美激情| 久久精品国产亚洲一区二区| 亚洲伊人一本大道中文字幕| 久久嫩草精品久久久久| 香蕉视频成人在线观看| 欧美日本乱大交xxxxx| 欧美激情网友自拍| 激情欧美一区| 欧美在线免费一级片| 午夜精品久久久久久久久| 欧美激情综合色| 国产精品欧美精品| 99在线精品视频在线观看| 久久久久久高潮国产精品视| 亚洲一区二区三区在线播放| 欧美成人官网二区| 欧美成年人网| 一区二区三区亚洲| 欧美一区二区精品在线| 午夜宅男欧美| 国产精品一区=区| 亚洲一区久久| 亚洲欧美国产日韩天堂区| 欧美午夜在线视频| 中文网丁香综合网| 午夜精品久久久久久久久久久久| 欧美日韩精品是欧美日韩精品| 亚洲国产成人在线播放| 亚洲人体影院| 欧美日韩不卡视频| 夜夜嗨av一区二区三区 | 久久男人资源视频| 国产一区二区日韩精品欧美精品| 亚洲欧美国产精品专区久久| 午夜影院日韩| 国产又爽又黄的激情精品视频| 欧美一进一出视频| 男女视频一区二区| 亚洲免费久久| 国产精品久久久久久久久久ktv| 亚洲视频一区二区在线观看| 香蕉视频成人在线观看| 国产综合一区二区| 欧美sm重口味系列视频在线观看| 亚洲精品日韩综合观看成人91| 中国成人在线视频| 国产午夜精品全部视频播放| 久久久久久久尹人综合网亚洲 | 18成人免费观看视频| 欧美ed2k| 亚洲一区三区视频在线观看 | 亚洲精品中文字幕女同| 欧美日韩在线观看一区二区| 亚洲欧美成人网| 欧美jjzz| 亚洲一品av免费观看| 国产视频一区二区在线观看| 久久午夜精品| 亚洲一级片在线看| 欧美成人r级一区二区三区| 亚洲精品美女在线观看| 国产精品久久久久9999| 久久另类ts人妖一区二区| 亚洲伦理在线观看| 久久婷婷国产综合精品青草| 一本大道久久精品懂色aⅴ | 欧美激情综合在线| 亚洲自拍偷拍视频| 亚洲高清在线| 久久深夜福利免费观看| 一区二区三区免费看| 伊人久久综合97精品| 国产精品第十页| 久热精品视频在线| 久久久久久久国产| 国产一区二区你懂的| 欧美日韩精品在线播放| 久久久久久久久久久一区| 亚洲无线视频| 99国产一区| 亚洲成人中文| 日韩亚洲欧美中文三级| 欧美在线视频日韩| 一区二区三区高清不卡| 欲香欲色天天天综合和网| 国产精品国产一区二区| 欧美激情亚洲自拍| 六月婷婷一区| 久久久久久久高潮| 久久国产精品久久久久久久久久 | 亚洲大胆在线|