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

longshanks

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  14 Posts :: 0 Stories :: 214 Comments :: 0 Trackbacks

常用鏈接

留言簿(10)

我參與的團隊

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

GP技術的展望——先有鴻鈞后有天

莫華楓


    自從高級語言出現以來,類型始終是語言的核心。幾乎所有語言特性都要以類型作為先決條件。類型猶如天地,先于萬物而存在。但是,是否還有什么東西比類型更加原始,更加本質,而先于它存在呢?請往下看。:)

泛型和類型

    泛型最簡短最直觀的描述恐怕應該是:the class of type。盡管這樣的描述不算最完備,但也足以說明問題。早在60年代,泛型的概念便已經出現。最初以“參數化類型”的名義存在。70年代末期發展起來的 恐龍級的Ada(我的意思不是說Augusta Ada Byron Lovelace伯爵夫人是恐龍,從畫像上看,這位程序員的祖師奶長得相當漂亮:)),尚未擁有oop(Ada83),便已經實現了泛型(Generic)。盡管泛型歷史悠久,但真正全面地發展起來,還是在90年代初, 天才的Alexander A. Stepanov創建了stl,促使了“泛型編程”(Generic Programming)的確立。
    出于簡便的目的,我套用一個老掉牙的“通用容器”來解釋泛型的概念。(就算我敷衍吧:P,畢竟重頭戲在后面,具體的請看前面給出的鏈接)。假設我在編程時需要一個int類型的棧,于是我做了一個類實現這個棧:
    class IntStack {...};
    用的很好。過了兩天,我又需要一個棧,但是類型變成了double。于是,我再另寫一個:
    class DoubleStack {...};
    不得了,好象是通了馬蜂窩,不斷地出現了各種類型的棧的需求,有string的,有datetime的,有point的,甚至還有一個Dialog的。每 種類型都得寫一個類,而且每次代碼幾乎一樣,只是所涉及的類型不同而已。于是,我就熱切地期望出現一種東西,它只是一個代碼的框架,實現了stack的所 有功能,只是把類型空著。等哪天我需要了,把新的類型填進去,便得到一個新的stack類。
    這便是泛型。
    但是,僅僅這些,還不足以成就GP的威名。
    我有一個古怪的需求(呵呵,繼續敷衍。:)):
    做一個模板,內部有一個vector<>成員:
    template<typename T> A
    {
        ...
        vector<T> m_x;
    };
    可是,如果類型實參是int類型的話,就得用set<>。為了使用的方便,模板名還得是A。于是,我們就得使用下面的技巧:
    template<> A<int>
    {
        ...
        set<T> m_x;
    };
    這叫特化(specialization),相當于告訴編譯器如果類型實參是int,用后面那個。否則,用前面的。特化實際上就是根據類型實參由編譯器執行模板的選擇。換句話說,特化是一種編譯期分派技術。
    這里還有另一個更古怪需求:如果類型實參是指針的話,就用list<>。這就得用到另一種特化了:
    template<typename T> A<T*>
    {
        ...
        list<T> m_x;
    }
    這是局部特化(partial specialization),而前面的那種叫做顯式特化(explicit specialization),也叫全特化。局部特化則是根據類型實參的特征(或者分類)執行的模板選擇。
    最后,還有一個最古怪的需求:如果類型實參擁有形如void func(int a)成員函數的類型,那么就使用deque。這個...,有點難。現有的C++編譯器,是無法滿足這個要求的。不過希望還是有的,在未來的新版C++09中,我們便可以解決這個問題。

Concept和類型

    concept是GP發展必然結果。正如前面所提到的需求,我們有時候會需要編譯器能夠鑒識出類型的某些特征,比如擁有特定的成員等等,然后執行某種操作。下面是一個最常用的例子:
    swap()是一個非常有用的函數模板,它可以交換兩個對象的內容,這是swap手法的基礎。swap()的基本定義差不多是這樣:
    template<typename T> swap(T& lhs, T& rhs) {
        T tmp(lhs);
        lhs=rhs;
        rhs=tmp;
    }
    但是,如果需要交換的對象是容器之類的大型對象,那么這個swap()的性能會很差。因為它執行了三次復制,這往往是O(n)的。標準容器都提供了一個 swap成員函數,通過交換容器內指向數據緩沖的指針,獲得O(1)的性能。因此,swap()成員是首選使用的。但是,這就需要程序員識別對象是否存在 swap成員,然后加以調用。如果swap()函數能夠自動識別對象是否存在swap成員,那么就可以方便很多。如果有swap成員,就調用成員,否則, 就是用上述通過中間變量交換的版本。
    這就需要用到concept技術了:
    template<Swappable T> void swap(T& lhs, T& rhs) {
        lhs.swap(rhs);
    }
    這里,Swappable是一個concept:
    concept Swappable<typename T> {
        void T::swap(T&);
    }
    于是,如果遇到擁有swap成員函數的對象,正好符合Swappable concept,編譯器可以使用第二個版本,在O(1)復雜度內完成交換。否則,便使用前一個版本:
    vector a, b;
    ... //初始化a和b
    swap(a,b); //使用后一個版本
    int c=10, d=23;
    swap(c, d); //使用前一個版本
    這里的swap()也是運用了特化,所不同的是在concept的指導下進行的。這樣的特化有時也被稱作concept based overload。
    從上面的例子中可以看到,原先的特化,無論是全特化,還是局部特化,要么特化一個類型,要么特化一個大類(如指針)的類型。但無法做到更加精細。比如,我 希望一個模板能夠針對所有的整數(int,long,short,char等)進行特化,這在原先是無法做到的。但擁有了concept之后,我們便可以 定義一個代表所有整數的concept,然后使用這個整數concept執行特化。換句話說,concept使得特化更加精細了,整個泛型系統從原來“離 散”的變成了“連續”的。
    不過上面那個concept特化的模板看起來實在不算好看,頭上那一坨template...實在有礙觀瞻。既然是concept based overload,那么何不直接使用重載的形式,而不必再帶上累贅的template<...>:
    void fun(anytype a){...} //#1,anytype是偽造的關鍵字,表示所有類型。這東西最好少用。
    void fun(Integers a){...} //#2,Integers是concept,表示所有整型類型
    void fun(Floats a){...} //#3,Floats是concept,表示所有浮點類型
    void fun(long a){...} //#4
    void fun(int a){...} //#5
    void fun(double a){...} //#6
    ...
    int x=1;
    long y=10;
    short z=7;
    string s="aaa";
    float t=23.4;
    fun(x); //選擇#5
    fun(y); //選擇#4
    fun(z); //選擇#2
    fun(s); //選擇#1
    fun(t); //選擇#3
    這種形式在語義上與原來的模板形式幾乎一樣。注意,是幾乎。如下的情形是重載形式無法做到的:
    template<Integers T> T swap(T lhs, T rhs) {
        T temp(lhs);
        ...
    }
    這里,模板做到了兩件事:其一,模板萃取出類型T,在函數體中,可以使用T執行一些操作,比如上述代碼中的臨時對象temp的構造。這個問題容易解決,因為萃取類型T還有其他的方法,一個typeof()操作符便可實現:
    Integers swap(Integers lhs, Integers rhs) {
        typeof(lhs) temp(lhs);
        ...
    }
    其二,模板保證了lhs,rhs和返回值都是同一類型。這個問題,可以通過施加在函數上的concept約束解決:
    Integers swap(Integers lhs, Integers rhs)
        requires SameType<lhs, rhs>
            && SameType<lhs, retval> {  //retval是杜撰的關鍵字,用以表示返回值
        typeof(lhs) temp(lhs);
        ...
    }
    相比之下,重載形式比較繁瑣。總體而言,盡管重載形式冗長一些,但含義更加明確,更加直觀。并且在concept的接口功能作用下,對參數類型一致的要求 通常并不多見(一般在基本類型,如整型等,的運算處理中較多見。因為這些操作要求類型有特定的長度,以免溢出。其他類型,特別是用戶定義類型,通常由于封 裝的作用,不會對類型的內部特性有過多要求,否則就不應使用泛型算法)。如果可以改變語法的話,那么就能用諸如@代替typeof,==代替 SameType的方法減少代碼量:
    Integers swap(Integers lhs, Integers rhs)
        requires @lhs == @rhs && @lhs == @retval {
        @lhs temp(lhs);
        ...
    }
   

Concept、類型和對象

    事情還可以有更加夸張的發展。前面對泛型進行了特化,能不能對類型也來一番“特化”呢?當然可以:
    void fun(int a);
    void fun(int a:a==0); //對于類型int而言,a==0便是“特化”了
    更完整的,也可以有“局部特化”:
    void fun(int a); //#1
    void fun(int a:a==0); //#2
    void fun(int a:a>200); //#3
    void fun(int a:a<20&&a>10); //#4
    void fun(int a:(a>70&&a<90)||(a<-10)); //#5
    ...
    int a=0, b=15, c=250, d=-50;
    fun(80); //使用#5
    fun(50); //使用#1
    fun(a); //使用#2
    fun(b); //使用#4
    fun(c); //使用#3
    fun(d); //使用#5
    實際上,這無非是在參數聲明之后加上一組約束條件,用以表明該版本函數的選擇條件。沒有約束的函數版本在沒有任何約束條件匹配的情況下被選擇。對于使用立 即數或者靜態對象的調用而言,函數的選擇在編譯期執行,編譯器根據條件直接調用匹配的版本。對于變量作為實參的調用而言,則需要展開,編譯器將自動生成如 下代碼:
    //首先將函數重新命名,賦予唯一的名稱
    void fun_1(int a); //#1
    void fun_2(int a); //#2
    void fun_3(int a); //#3
    void fun_4(int a); //#4
    void fun_5(int a); //#5
    //然后構造分派函數
    void fun_d(int a) {
        if(a==0)
            fun_2(a);
        else if(a>200)
            fun_3(a);
        ...
        else
            fun_1(a);
    }
    在某些情況下,可能需要對一個對象的成員做出約束,此時便可以采用這種形式:
    struct A
    {
        float x;
    };
    ...
    void fun(A a:a.x>39.7);
    ...
    這種施加在類型上的所謂“特化”實際上只是一種語法糖,只是由編譯器自動生成了分派函數而已。這個機制在Haskell等語言中早已存在,并且在使用上帶 來很大的靈活性。如果沒有這種機制,那么一旦需要增加函數分派條件,那么必須手工修改分派函數。如果這些函數,包括分派函數,是第三方提供的代碼,那么修 改將是很麻煩的事。而一旦擁有了這種機制,那么只需添加一個相應的函數重載即可。
    當concept-類型重載和類型-對象重載混合在一起時,便體現更大的作用:
    void fun(anytype a);
    void fun(Integers a);
    void fun(Floats a);
    void fun(long a);
    void fun(int a);
    void fun(double a);
    void fun(double a:a==0.8);
    void fun(short a:a<10);
    void fun(string a:a=="abc");
    ...
    concept-類型-對象重載體系遵循一個原則:優先選擇匹配的函數中最特化的。這實際上是類型重載規則的擴展。大的來說,所有類型比所屬的 concept更加特化,所有對象約束比所屬的類型更加特化。對于concept而言,如果concept A refine自concept B,那么A比B更加特化。同樣,如果一個類型的約束強于另一個,那么前一個就比后一個更加特化,比如a==20比a>10更加特化。綜合起來,可以 有這樣一個抽象的規則:兩個約束(concept,或者施加在對象上的約束)A和B,作用在類型或者對象上分別產生集合,如果A產生的集合是B產生的集合 的真子集,那么便認為A比B更加特化。
    根據這些規則,實際上可以對一個函數的重載構造出一個“特化樹”:

    越接近樹的根部,越泛化,越接近葉子,越特化。調用時使用的實參便在這棵“特化樹”上搜索,找到最匹配的函數版本。
    concept-類型-對象體系將泛型、類型和對象統一在一個系統中,使得函數的重載(特化)具有更簡單的形式和規則。并且,這個體系同樣可以很好地在類模板上使用,簡化模板的定義和使用。

類模板

    C++的類模板特化形式并不惹人喜愛:
    template<typename T> A{...}; //基礎模板
    template<> A<int>{...}; //顯式特化(全特化)
    template<typename T> A<T*>{...}; //局部特化
    在C++09中,可以直接用concept定義模板的類型形參:
    template<Integers T> A{...};
    實質上,這種形式本身就是一種局部特化,因而原本那種累贅局部特化形式可以廢除,代之以concept風格的形式:
    template<Pointer T> A{...}; //Pointer表示此處采用指針特化模板
    同樣,如果推廣到全特化,形式也就進一步簡單了:
    template<int> A{...}; //這個形式有些突兀,這里只打算表達這個意思,應該有更“和諧”的形式
    如果模板參數是對象,則使用現有的定義形式:
    template<int a> A{...};
    更進一步,可以引入對象的約束:
    template<int a:a>10> A{...};
    此外,C++中在模板特化之前需要有基礎模板。但實際上這是多余的,D語言已經取消了這個限制,這對于簡化模板的使用有著莫大的幫助。

從本質上講...

    從本質上講,我們可以把所有類型看作一個集合T={ti},而concept則是施加在類型集合上的約束。通過concept這個約束,我們便可以獲得類 型集合T的一個子集C。理論上,所有concept所對應的類型子集Cj構成了類型集合的冪集{Cj}。在{Cj}中,有兩類類型子集是很特殊的。一組是 T本 身,即所有類型。存在一個concept不對T施加任何約束,便得到了C0=T。第二類則是另一個極端,存在一組concept,施加在T上之后所得的類 型子集僅包含一個類型:Ci={ti}。由于這組concept與類型存在一一對應的關系,那么我們便可以用這組concept來指代類型。也就是把類型 作為特殊的concept處理。如此,concept便同類型統一在一個體系中。這種處理可以使我們獲得極大的好處。
    這組特殊的concept仍舊使用對應的類型名作為稱謂,仍舊稱之為“類型”,但其本質上還是concept。任何一個類型,一旦創建,也就創建了相應的特殊concept。如果在模板特化中使用一個類型的時候,實際上就是在使用相對應的那個特殊concept:
    void func(typeA a); //盡管使用了類型名typeA,但實際上這里所指的是typeA所對應的那個特殊concept。
    在這個concept體系的作用下,函數模板的特化和重載整個地統一起來(concept based overload)。
    至于作用在類型上的那種“特化”,也是同樣的道理。對于一個類型T而言,它所有的對象構成一個集合O。如果存在一組約束作用于O,那么每 一個約束對應著O的一個子集。理論上,我們可以構造出一組約束,使得他們同O的每一個子集一一對應。同樣,這些子集中有兩類子集比較特殊。一類是所有對象 的集合。另一類便是只有一個對象的子集。于是,我們可以使用這組特殊對象子集所對應的約束指代相應的對象。也就是將對象看作特殊的約束。如此,類型和對象 也被統一在一個系統中了。
    進而,類型在邏輯上被作為特殊concept處理,對象則被作為特殊的類型處理。于是,這三者便可以統一在一個體系下,一同參與特化。

總結

    盡管形式不能代表本質,但形式的變化往往會帶來很多有益的進步。更重要的是,很多本質上的變化總會伴隨著形式上的改變。通過將concept、類型和對象 在邏輯上整合到統一的體系之中,便可以促使模板、特化、函數重載等機制在形式上達成統一。從而能夠簡化這些功能的使用。這也是當前重視語言(工具)易用性 的潮流的一個必然訴求。這個形式上的統一并非語法糖之類的表面變化。而是完全依賴于concept這個新型的類型描述(泛型)系統的確立和發展。 concept的出現,彌補了以往泛型的不足,找回了泛型系統缺失的環節,彌補了泛型同類型之間的裂痕。在此作用下,便可以構建起concept-類型- 對象的抽象體系,用統一的系統囊括這三個原本分立的概念。在這個新的三位一體的系統下,使得模板的特化和重載擁有了相同的形式,進而獲得更直觀的語義,和 更好的易用性。
posted on 2008-07-26 19:44 longshanks 閱讀(1934) 評論(10)  編輯 收藏 引用

Feedback

# re: GP技術的展望——先有鴻鈞后有天 2008-07-26 21:25 oldrev
這樣的話程序中會不會出現無數只為約束函數參數而沒其他作用的 concepts,重走 C#/Java 中 interface 的老路?  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-26 22:28 clear
c++0x 的concept不需要顯式聲明的,比如那個Swapable,任何一個類型,只要有一個滿足其條件的swap成員函數,就自動成為這個concept的一個特例存在
所以不會像java里面那樣對所有的類都implement一堆的interface  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-26 22:33 Kevin Lynx
longshanks終于又發文了。學習。  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-26 22:36 空明流轉
其實語法糖很重要。。。。  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 [未登錄] 2008-07-26 23:06 foxtail
博大精深的C++ 呵呵  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-27 00:40 bneliao
gp要一桶漿糊了  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-27 06:54 longshanks
to oldrev兄:
我不太理解“只為約束函數參數而沒其他作用的 concepts”這個概念,能否給個例子。這個問題我這么想:concept以及runtime concept同oop的interface的差異我以前的blog和toplanguage討論中都談論過。本質上,interface是“用一個類型來表征一組類型”,邏輯上就不那么和諧。而concept則是用一個獨立的,專門用于描述一組類型的概念實現這個功能。interface的弊端,比如侵入的接口、造成類型耦合等等,在concept中不會存在。運用concept,我們可以消除這部分問題。至于其他的interface問題,可能來自于需求和設計,通常也無法全部通過這種技術手段消除。
當然就像clear兄所說,concept可以auto(需要在定義concept指定auto),這也消除了不少麻煩。只是auto需要謹慎,只有那些含有公共語義約定的concept,比如swappable、copyable等等,以及形式(成員)非常特殊,不可能有其他語義的類型與之混淆的情況下,才可以使用,否則容易引起混亂。  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-27 10:07 oldrev
@longshanks

在大多數地方 concept 的用途和 interface 是差不多的,定義一個 Copyable 的 concept 和定義一個 ICopyable 是一樣的麻煩,雖然 concept 是非侵入的。
  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-27 11:10 longshanks
@oldrev
這個就沒辦法了。這些接口都是需求設計驅使的,只是不同的手段實現而已。這方面的問題由于沒有廣泛的應用,還不太清楚,需要實踐檢驗。
concept相比interface的直接好處在于兩點:1、不需要在接口實現類型產生前定義concept,任何時候都可以,這樣可以減少設計上的壓力。這是非侵入的好處。2、concept驅動下的模板在runtime和compiletime是相同的,也就是同一個模板可以同時用于runtime和static,而不需要另搞一套。
間接的好處是會對語言整個模型產生根本性的影響,從而消除語言某些方面的復雜性和缺陷。這個我打算在下一篇blog里探討。  回復  更多評論
  

# re: GP技術的展望——先有鴻鈞后有天 2008-07-28 15:18 oldrev
@longshanks
期待ing....  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            好吊日精品视频| 一本到高清视频免费精品| 亚洲国产精品一区二区第一页| 香蕉尹人综合在线观看| 亚洲午夜精品17c| 国产视频在线一区二区 | 国产精品亚洲欧美| 久久精品成人| 亚洲一区日韩在线| 亚洲图片欧美日产| 亚洲欧美在线x视频| 亚洲自拍偷拍一区| 狠狠色狠狠色综合| 91久久精品www人人做人人爽| 老司机成人在线视频| 99精品国产一区二区青青牛奶| 亚洲伦理一区| 国产综合色在线视频区| 亚洲国产欧美一区二区三区久久| 欧美久久一级| 国产精品亚洲аv天堂网| 美女999久久久精品视频| 欧美区国产区| 久久噜噜噜精品国产亚洲综合| 欧美v国产在线一区二区三区| 亚洲天堂第二页| 久久在线免费视频| 欧美成人69av| 性欧美videos另类喷潮| 欧美精品国产精品| 夜色激情一区二区| 亚洲欧美一级二级三级| 久久久久国产免费免费| 一区二区欧美在线观看| 久久gogo国模裸体人体| 在线视频亚洲一区| 久久久蜜桃一区二区人| 亚洲欧美日韩一区二区在线 | 亚洲欧美日本日韩| 亚洲精品久久久久久一区二区| 国产精品久久久久aaaa九色| 亚洲人成免费| 欧美二区在线| 国产伦一区二区三区色一情| 亚洲福利视频一区| 国内成人精品一区| 亚洲中无吗在线| 一区二区三区四区五区视频| 免费成人黄色片| 欧美.com| 亚洲第一视频网站| 久久精品中文字幕免费mv| 羞羞色国产精品| 国产精品v欧美精品v日韩| 亚洲精品乱码久久久久久久久| 亚洲国产经典视频| 久久综合一区二区三区| 鲁大师成人一区二区三区| 国产一区二区三区在线观看免费| 中文亚洲欧美| 亚洲欧美视频| 国产欧美欧美| 亚洲综合电影| 欧美色区777第一页| 一区二区三区成人| 亚洲欧美日韩另类精品一区二区三区| 欧美日本精品| 亚洲视频综合| 久久aⅴ国产紧身牛仔裤| 国产欧美日本一区视频| 欧美有码在线观看视频| 久久久一本精品99久久精品66| 国产一区二区三区观看| 久久久久久香蕉网| 亚洲大片一区二区三区| 亚洲精品中文字幕女同| 欧美视频中文一区二区三区在线观看| 亚洲人成亚洲人成在线观看| 亚洲手机视频| 国产一区二区欧美日韩| 免费国产自线拍一欧美视频| 亚洲精品免费在线观看| 亚洲欧美日韩在线一区| 国产一区二区三区四区在线观看| 久久免费高清| 亚洲人成网站在线播| 午夜欧美电影在线观看| 狠狠综合久久| 欧美日韩一二三四五区| 欧美在线观看视频| 亚洲激情视频| 久久国内精品自在自线400部| 亚洲福利精品| 国产精品久线观看视频| 久久久久99| 一区二区三区精品| 久久性天堂网| 亚洲一区二区影院| 在线观看日韩www视频免费| 欧美日韩在线一区| 久久久国产亚洲精品| 99这里只有精品| 久久影院午夜论| 亚洲一区二区毛片| 亚洲经典三级| 国产亚洲精品久久久久动| 欧美激情一区二区三区在线| 亚洲欧美日韩在线高清直播| 欧美a级一区| 久久五月天婷婷| 亚洲婷婷在线| 亚洲三级电影全部在线观看高清 | 欧美视频三区在线播放| 久久精品国产77777蜜臀| 亚洲免费大片| 亚洲成人在线视频播放 | 久久黄金**| 一区二区三区免费网站| 亚洲国产精品成人综合色在线婷婷| 午夜欧美精品| 在线综合欧美| 日韩一级黄色av| 亚洲高清精品中出| 激情欧美一区二区三区| 久久精品亚洲热| 亚洲一区二区高清| 一本色道**综合亚洲精品蜜桃冫 | 久久一区视频| 久久久久久久网站| 欧美一区二区三区在线看| 亚洲一本大道在线| 一本到12不卡视频在线dvd| 亚洲精品免费看| 亚洲激情在线观看视频免费| 亚洲国产福利在线| 亚洲国产精品va在线看黑人动漫| 蜜桃av综合| 免费视频一区| 欧美高清视频一区二区| 欧美国产亚洲另类动漫| 亚洲高清免费| 亚洲精品中文字幕在线观看| 亚洲精品四区| 一二三区精品| 亚洲小说区图片区| 欧美在线一级视频| 久久久久久久久综合| 久久亚洲欧美国产精品乐播| 久久青草久久| 欧美va天堂在线| 欧美日韩精品不卡| 国产精品系列在线| 国产自产精品| 伊人久久综合| 亚洲精品一区二区三区蜜桃久 | 亚洲区中文字幕| 夜夜嗨av一区二区三区| 亚洲欧美国产日韩天堂区| 欧美自拍丝袜亚洲| 免费不卡欧美自拍视频| 亚洲国产成人久久综合一区| 亚洲精品乱码久久久久久蜜桃91| 在线视频你懂得一区二区三区| 亚洲视频中文| 久久综合色婷婷| 欧美色欧美亚洲另类二区| 国产欧美一区二区三区久久人妖| 精品福利av| 亚洲一区二区免费在线| 久久久欧美一区二区| 亚洲国产裸拍裸体视频在线观看乱了中文 | 久久久亚洲一区| 亚洲高清精品中出| 亚洲一区一卡| 欧美不卡激情三级在线观看| 一本在线高清不卡dvd | 欧美一区二区三区免费观看视频| 性感少妇一区| 免费欧美网站| 国产日韩欧美一二三区| 亚洲精品国产精品国自产在线| 亚洲欧美久久久| 欧美国产日本| 午夜视频在线观看一区| 欧美精品久久天天躁| 国产一区二区三区丝袜| 亚洲视频高清| 欧美国产精品久久| 欧美在线播放| 国产精品高潮呻吟久久av无限| 亚洲高清视频一区| 欧美一区二区三区播放老司机 | 久久久精品一区二区三区| 99re热这里只有精品免费视频| 久久久噜噜噜久久久| 国产伦精品一区二区| 亚洲桃花岛网站| 最新成人av网站| 久久字幕精品一区| 国内自拍一区|