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

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>
            亚洲欧美日韩在线综合| 久久福利电影| 国产精品女主播在线观看| 欧美理论在线| 欧美日韩一区精品| 国产精品va在线播放| 国产精品尤物| 国产综合久久| 亚洲精品久久久久久久久| 99热在线精品观看| 亚洲一区二区三区色| 久久精品国产亚洲5555| 欧美a级片网站| 99视频精品免费观看| 亚洲综合国产精品| 男同欧美伦乱| 国产九区一区在线| 91久久精品国产91性色tv| 亚洲视频在线一区| 免费成人黄色| 亚洲午夜羞羞片| 久久综合伊人77777麻豆| 欧美色道久久88综合亚洲精品| 国产日韩在线看| 99国产精品久久久久老师| 欧美一区二区三区日韩视频| 欧美激情第10页| 午夜精品久久久久久久99樱桃 | 国产亚洲综合在线| 亚洲精品久久久久久久久久久久久 | 欧美激情视频网站| 国产精品视频免费观看| 亚洲国产一区二区三区a毛片| 猛干欧美女孩| 国产伦一区二区三区色一情| 亚洲人成在线观看网站高清| 欧美一区二区三区四区在线观看| 欧美高清在线视频观看不卡| 亚洲综合成人在线| 欧美精品久久一区二区| 狠狠色狠狠色综合日日五| 亚洲一二三区视频在线观看| 欧美黑人多人双交| 久久大逼视频| 国产精品影片在线观看| 亚洲私人影院| 亚洲精品影院| 欧美精品国产一区| 亚洲高清在线观看| 久久综合色88| 久久精品盗摄| 国产一区二区成人| 午夜精品免费视频| 中日韩美女免费视频网址在线观看| 你懂的亚洲视频| 影音先锋中文字幕一区二区| 久久精彩视频| 香蕉国产精品偷在线观看不卡| 国产精品二区三区四区| 亚洲网友自拍| 在线一区日本视频| 国产精品欧美风情| 午夜精品99久久免费| 一区二区三区免费在线观看| 欧美日韩高清在线| 亚洲日韩第九十九页| 亚洲福利视频二区| 久久精品视频在线播放| 红桃av永久久久| 美玉足脚交一区二区三区图片| 久久久久久久综合日本| 亚洲国产精品视频| 亚洲精品综合| 国产精品乱码人人做人人爱| 午夜精品在线| 欧美在线视频网站| 亚洲国产日日夜夜| 99天天综合性| 国产性色一区二区| 亚洲第一精品在线| 欧美午夜女人视频在线| 久久精品91| 美女主播一区| 亚洲一区三区电影在线观看| 亚洲欧美日韩国产综合在线 | 亚洲视频一二| 亚洲欧美日韩一区在线观看| 国内精品国语自产拍在线观看| 免费成人毛片| 欧美日韩亚洲激情| 久久一区二区三区四区| 99精品久久久| 国产欧美日韩一区| 亚洲第一黄色| 国产精品视频专区| 农夫在线精品视频免费观看| 欧美激情中文不卡| 久久国产日本精品| 欧美日韩国产探花| 噜噜噜91成人网| 国产精品swag| 亚洲国产精品美女| 国产欧亚日韩视频| 亚洲三级电影在线观看 | 久久精品国产一区二区三| 亚洲精品视频免费| 香蕉久久夜色| 亚洲视频免费在线| 美女精品一区| 欧美在线影院| 欧美日韩亚洲一区二区三区| 久久婷婷蜜乳一本欲蜜臀| 国产精品va在线| 亚洲人成在线观看| 91久久在线| 久久久久久电影| 欧美一区不卡| 国产精品毛片大码女人| 亚洲日本精品国产第一区| 激情久久综合| 欧美在线视频一区二区三区| 亚洲自拍偷拍网址| 欧美人与性动交a欧美精品| 免费一区二区三区| 极品av少妇一区二区| 欧美一区二区免费视频| 性一交一乱一区二区洋洋av| 欧美日韩一区二区欧美激情 | 亚洲国产毛片完整版 | 曰本成人黄色| 欧美亚洲免费高清在线观看| 亚洲一卡久久| 欧美三区免费完整视频在线观看| 欧美激情精品久久久久| 伊人伊人伊人久久| 久久女同互慰一区二区三区| 久久久精品国产99久久精品芒果| 国产精品视频导航| 亚洲欧美在线看| 久久久久久久欧美精品| 国产一区白浆| 久久男人资源视频| 欧美成年人网站| 亚洲国产高清一区二区三区| 久久蜜桃资源一区二区老牛 | 久久大香伊蕉在人线观看热2| 亚洲欧美色一区| 国产精品一卡| 欧美一区二区黄色| 免费成人在线观看视频| 欧美伦理一区二区| 91久久精品一区二区别| 欧美在线黄色| 99成人精品| 欧美午夜精品久久久久免费视| 日韩写真视频在线观看| 亚洲色在线视频| 美女精品一区| 欧美暴力喷水在线| 亚洲人成毛片在线播放女女| 亚洲国产精品久久91精品| 一区二区三区av| 99精品久久| 国产欧美综合一区二区三区| 亚洲在线观看免费视频| 一区二区三区在线看| 日韩亚洲在线| 欧美激情精品久久久久久蜜臀| 亚洲女人小视频在线观看| 欧美成人有码| 亚洲美女在线看| 午夜精品一区二区三区在线视| 国内视频一区| 久久不射电影网| 久久综合激情| 亚洲大胆av| 中文高清一区| 国产精品啊v在线| 国产精品亚洲一区二区三区在线| 久久综合国产精品台湾中文娱乐网| 久久中文字幕一区| 欧美日韩黄视频| 国外精品视频| 久久久一本精品99久久精品66| 免费欧美网站| 99在线精品观看| 欧美日韩在线播放| 亚洲韩国精品一区| 亚洲欧美一区二区在线观看| 欧美成人国产va精品日本一级| 欧美亚一区二区| 久久精品国产亚洲aⅴ| 噜噜噜噜噜久久久久久91| 亚洲国产一区二区三区在线播| 亚洲高清三级视频| 国产伦理一区| 欧美久久精品午夜青青大伊人| 亚洲一区二区动漫| 免费观看在线综合| av成人国产|