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

posts - 297,  comments - 15,  trackbacks - 0
出處 http://www.shnenglu.com/cexer/archive/2008/07/06/55484.html

  VC當(dāng)中有一個鮮為人知的關(guān)鍵字,除了微軟自己的代碼,我從未在任何地方看到有人用過它。雖然它的功能很強(qiáng)大,不過除非設(shè)計上的問題或是一些無法排除的困難,否則幾乎從不會需要用到它的功能。但是有時候,它確實能作為一個最簡單的解決方案而讓某些設(shè)計過程事半功倍。

  借用 CCTV10《走近科學(xué)》的語氣:那么這個神秘的關(guān)鍵關(guān)鍵字到底是什么呢?它又實現(xiàn)了什么神奇的功能呢?帶著這一連串的疑問,讓我們先來看一個具體的例子。

  我在自己曾經(jīng)寫的一個GUI框架當(dāng)中,為了實現(xiàn)消息與處理函數(shù)自動映射的,就需要求助于這種功能。比如說有一個窗口類,它包含若干消息處理函數(shù)和一個消息與處理函數(shù)的映射 map:(請無視當(dāng)中的 show() 和 create() 函數(shù),與主題無關(guān))

    class Window
{
typedef UINT _Message;
typedef LRESULT (Window::*_Handler)(_Message);

map<_Message,_Handler> m_handlerMap;

public:
bool show();
bool create();

public:
LRESULT onEvent( WindowEvent<WM_CREATE> );
LRESULT onEvent( WindowEvent<WM_DESTROY> );
};

  
  我需要利用模板元編程 從 0 到 WM_USER  進(jìn)行循環(huán)檢測,檢測 Window 類是否存在該消息對應(yīng)的處理函數(shù)。如果消息對應(yīng)的處理函數(shù)存在,那么就將消息與函數(shù)的映射放進(jìn) m_handlerMap 當(dāng)中。比如說消息 WM_CREATE,我檢測類 Window是否存在 LRESULT onEvent( WindowEvent<WM_CREATE> ) 成員函數(shù),在上例代碼中是存在的,于是我將這樣一個映射放進(jìn)m_handlerMap:(真正實現(xiàn)的時候,還要考慮函數(shù)的類型。不同類型的函數(shù),是不能直 接裝進(jìn) map 當(dāng)中的。不過在這里請無視例子當(dāng)中涉及的所有類型轉(zhuǎn)換,與主題無關(guān))

    pair<WM_CREATE,&Window::onEvent>


  這樣就達(dá)到了消息自動映射的目的。而不用像MFC一樣手寫宏去映射。(最后通過努力的確達(dá)到了我的目的,我的GUI框架能夠進(jìn)行自動消 息映射了,然而可以預(yù)見,由于幾千個(0-WM_USER)循環(huán),編譯期的速度受到極大影響。所以最終我還是拋棄了這種自動映射實現(xiàn),而采用了更高效神奇 的方法,這是后話也與本主題無關(guān)就先不提)。

  要實現(xiàn)以上的自動映射功能就引出了這樣一個難題:如何編譯期檢測類的某特定名字的成員是否存在。

  功能不負(fù)有心人,經(jīng)過爬山涉水翻山越嶺,我終于在 MSDN 一個偏遠(yuǎn)角落里找著了傳說當(dāng)中那個神秘的關(guān)鍵字:__if_exists(其實還有一個 __if_not_exists)。MSDN 當(dāng)中這樣說明:__if_exists (__if_not_exists)允許你針對某符號的存在與否條件性地執(zhí)行語句。使用語法:(注意檢測的是“存在性”,而不是值)

    __if_exists ( /*你要檢測存在性的函數(shù)或變量的名字*/ ) { 
 //做些有用的事
}


  MSDN當(dāng)中的示例代碼如下:
    // the__if_exists_statement.cpp
// compile with: /EHsc
#include <iostream>

template<typename T>
class X : public T {
public:
void Dump() {
std::cout << "In X<T>::Dump()" << std::endl;

__if_exists(T::Dump) {
T::Dump();
}

__if_not_exists(T::Dump) {
std::cout << "T::Dump does not exist" << std::endl;
}
}
};

class A {
public:
void Dump() {
std::cout << "In A::Dump()" << std::endl;
}
};

class B {};

bool g_bFlag = true;

class C {
public:
void f(int);
void f(double);
};

int main() {
X<A> x1;
X<B> x2;

x1.Dump();
x2.Dump();

__if_exists(::g_bFlag) {
std::cout << "g_bFlag = " << g_bFlag << std::endl;
}

__if_exists(C::f) {
std::cout << "C::f exists" << std::endl;
}

return 0;
}


  以上代碼的輸出如下:(未測試,此輸出為MSDN的說明文檔當(dāng)中的)

    In X<T>::Dump()
In A::Dump()
In X<T>::Dump()
T::Dump does not exist
g_bFlag = 1
C::f exists


  大概很少人見過這個關(guān)鍵字吧。雖然它們的功能與我的需求是如此的接近,但是面對如此強(qiáng)憾的關(guān)鍵字,我還是只能搖頭嘆息。我傷心地在文檔 里看到說明,__if_exists(__if_not_exists)關(guān)鍵字用于函數(shù)的時候,只能根據(jù)函數(shù)名字進(jìn)行檢測,而會忽略對參數(shù)列表的檢測,因 此沒有對重載函數(shù)的分辨能力,而正是我需要的。比如類 Window 有一個函數(shù):

    LRESULT Window::onEvent( WindowEvent<WM_DESTROY> )
{
//做些有用的事
}


  我用以下代碼來檢測 WM_CREATE 消息是否存在處理函數(shù):

    __if_exists(Window::onEvent)
  {
      //添加消息映射
   }


  即使 Window 類當(dāng)中不存在 LRESULT onEvent ( WindowEvent<WM_CREATE> ),以上測試也能通過。這是因為 __if_exists 關(guān)鍵字是不管函數(shù)重載的,如果存在一個 onEvent ,那么所有的檢測都能通過。這不是我想要的。我需要比 __if_exists 更強(qiáng)憾的檢測功能,強(qiáng)憾到能夠針對不同參數(shù)列表的同名函數(shù)(重載函數(shù))做出正確的存在性測試。

  于是我繼續(xù)翻山越嶺地尋找,從 CSDN 到 MSDN,從 SourceForge 到 CodeProject。要相信那句老話:“有心人天不負(fù)”。最后我在 CodeProject 上面看到一篇讓我醍醐灌頂?shù)奈恼拢?/p>

  Interface Detection by Alexandre Courpron

  這篇文章從原理到實現(xiàn),很詳細(xì)地說明地一種編譯期檢測技術(shù),先說明一下,由于VC7.1數(shù)千個bug當(dāng)中的一個,以下技術(shù)不能在VC++7.1或更低版本上使用。具體的實現(xiàn)在那篇文章當(dāng)中說得很詳盡了,還是在這兒贅述一下。

  Alexandre Courpron的實現(xiàn)方式基于C++的這樣一個規(guī)則:Substitution Failure Is Not An Error (簡稱SFINAE)。它的含義我也理解得比較含糊,不過它作用于重載函數(shù)的時候,可以這樣理解:對于一個函數(shù)調(diào)用,在匹配函數(shù)的過程當(dāng)中,如果最終能夠 有一個函數(shù)匹配成功,那么對其余函數(shù)的匹配如果失敗,編譯器也不會視為錯誤。聽起來有些麻煩,看Alexandre Courpron給出的例子:

    struct Test 
{
typedef int Type;
};

template < typename T >
void f(typename T::Type) {} // definition #1

template<typename T>
void f(T){} // definition #2

f<Test>(10); //call #1

f<int>(10); //call #2

  
  對于 call#1 編譯器直接匹配 definition#1 成功。對于 call#2,編譯器先用 definition#1 匹配 如下:

    void f( typename int::Type ) {}


  這顯然是不正確的。不過編譯器并沒有編譯失敗報告錯誤,因為下面的 definition#2 匹配成功,根據(jù) SFINAE的 規(guī)則,編譯器有權(quán)保持沉默 。

  雖然是個小小的規(guī)則,在平時幾乎不會注意它。然而在這兒,我們卻可以利用它實現(xiàn)編譯期檢測的強(qiáng)大功能了,一個最簡單的示例:

    #include <iostream>
using namespace std;
//
struct TestClass
{
void testFun();
};

struct Exists { char x;};
struct NotExists { char x[2]; };

template <void (TestClass::*)()>
struct Param ;

template <class T>
Exists isExists( Param<&T::testFun>* );

template <class T>
NotExists isExists( ... );
//
int main()
{
cout<<sizeof(isExists<TestClass>(0))<<endl;
}


  上面的代碼會輸出 1。說明一下檢測的過程:

  1. 編譯器遇到 isExists<TestClass>(0) 這一句,會去匹配 isExists 的兩個重載函數(shù)。不定長的參數(shù)優(yōu)先級更低,因此先匹配第一個函數(shù)。
  2. 第一個函數(shù)參數(shù)類型為 Param<&T::testFun>*,在這里是 Param<&TestClass::testFun>,編譯器在匹配這個參數(shù)類型的時候會嘗試實例化模板類 Param。
  3. 編 譯器嘗試用 &TestClass::testFun 去實例化 Param,因為 TestClass 確實存在一個 void (TestClass::*)() 類型,且名為 testFun 的成員函數(shù)。所以 Param 的實例化成功,因此參數(shù)匹配成功。
  4. 匹配第一個函數(shù)成功。編譯器決定 isExists<TestClass>(0) 這一句調(diào)用就是調(diào)用的第一個函數(shù)。
  5. 因為第一個函數(shù)返回的類型為 Exists,用 sizeof 取大小就是 1。

  如果是我們把 TestClass 的定義修改為:(僅把函數(shù)的參數(shù)類型改為 int )

    struct TestClass
{
void testFun(int);
};


  這一次代碼會輸出 2。因為在第3步的時候,由于 TestClass 沒有類型為 void (TestClass::*)(),且名為 testFun 的函數(shù),所以實例化 Param 會失敗,因此匹配第一個函數(shù)失敗。然后編譯器去匹配第二個函數(shù)。因為其參數(shù)類型是任意的,自然會匹配成功。結(jié)果會輸出 2。

  當(dāng)然這只是個最簡單的示例,通過模板包裝類。可以實現(xiàn)更靈活更強(qiáng)大的功能。比如回到那個自動消息映射的例子,用以下代碼就能夠?qū)崿F(xiàn)了:

//c++std
#include <iostream>
using namespace std;




//windows
#include <windows.h>



//detector
template<typename TWindow,UINT t_msg>
struct MessageHandlerDetector
{
typedef WindowEvent<t_msg> _Event;

struct Exists {char x;};
struct NotExists {char x[2];};

template<LRESULT (TWindow::*)(_Event)>
struct Param;

template<typename T>
static Exists detect( Param<&T::onEvent>* );

template<typename T>
static NotExists detect( ... );

public:
enum{isExists=sizeof(detect<TWindow>(0))==sizeof(Exists)};
};

//test classes
struct Window
{
LRESULT onEvent( WindowEvent<WM_CREATE> );
};

struct Button
{
LRESULT onEvent( WindowEvent<WM_DESTROY> );
};

//main
int main()
{
cout<<MessageHandlerDetector<Window,WM_CREATE>::isExists<<endl;
cout<<MessageHandlerDetector<Window,WM_DESTROY>::isExists<<endl;
cout<<MessageHandlerDetector<Button,WM_CREATE>::isExists<<endl;
cout<<MessageHandlerDetector<Button,WM_DESTROY>::isExists<<endl;

return 0;
}




  以上代碼會輸出:

    1
0
0
1


  以上的示例代碼再加上模板元編程,可以很輕易地實現(xiàn)消息的自動映射,具體實現(xiàn)這個已不在本貼的討論范圍并且這種自動映射的實現(xiàn),太過復(fù)雜,在編譯期沒有效率,且不夠靈活。不過在消息映射機(jī)制上來說,已稱得上是一種革命性的嘗試。

  在說完了這所有一切之后,再告訴你一個我最近才知道的秘密(不準(zhǔn)笑我孤陋寡聞):其實 boost 庫當(dāng)中已有相關(guān)功能的 MPL  工具存在,叫做 has_xxx。

  源文件:<boost\mpl\has_xxx.hpp>

  文檔:http://www.boost.org/doc/libs/1_35_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html

posted on 2008-07-19 13:50 chatler 閱讀(488) 評論(0)  編輯 收藏 引用 所屬分類: VC_MFC
<2010年11月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

常用鏈接

留言簿(10)

隨筆分類(307)

隨筆檔案(297)

algorithm

Books_Free_Online

C++

database

Linux

Linux shell

linux socket

misce

  • cloudward
  • 感覺這個博客還是不錯,雖然做的東西和我不大相關(guān),覺得看看還是有好處的

network

OSS

  • Google Android
  • Android is a software stack for mobile devices that includes an operating system, middleware and key applications. This early look at the Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.
  • os161 file list

overall

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲高清二区| 欧美国产一区二区| 欧美成人一品| 久久九九热re6这里有精品| 欧美日韩黄色大片| 免费日韩av片| 伊人久久噜噜噜躁狠狠躁| 亚洲午夜视频在线观看| 日韩一区二区精品葵司在线| 久久久久欧美精品| 久久九九久久九九| 国产色婷婷国产综合在线理论片a| 91久久中文| 亚洲国产精品欧美一二99| 亚洲欧美中文在线视频| 亚洲综合色自拍一区| 欧美日韩大片| 亚洲精品国偷自产在线99热| 亚洲片在线观看| 蜜桃av久久久亚洲精品| 男男成人高潮片免费网站| 激情综合激情| 久久久夜夜夜| 女女同性女同一区二区三区91| 很黄很黄激情成人| 欧美在线一二三四区| 久久国产精品毛片| 国产日韩欧美黄色| 久久av最新网址| 久久综合999| 在线观看久久av| 免费成人美女女| 亚洲国产专区校园欧美| 日韩视频免费观看| 欧美午夜精品久久久| 亚洲伊人久久综合| 欧美中文在线观看| 一区精品久久| 欧美好吊妞视频| 日韩亚洲成人av在线| 亚洲欧美日韩视频一区| 国产欧美日韩在线视频| 久久久不卡网国产精品一区| 亚洲大片在线| 亚洲一二三四区| 国产女主播视频一区二区| 欧美中文在线免费| 欧美国产日韩一区二区在线观看| 亚洲精品欧美精品| 国产精品大片| 久久久久久自在自线| 亚洲国产视频一区| 亚洲欧美在线网| 一区二区亚洲欧洲国产日韩| 欧美激情aaaa| 亚洲欧美激情视频| 欧美电影资源| 亚洲免费在线视频| 在线播放中文一区| 欧美三区在线视频| 久久精品国产欧美亚洲人人爽| 亚洲国产美女久久久久| 午夜精品福利一区二区蜜股av| 在线观看国产一区二区| 欧美日韩一区二区在线播放| 欧美有码在线观看视频| 亚洲精品视频一区二区三区| 久久久久看片| 一区二区三区四区五区视频| 国语自产精品视频在线看一大j8 | 国产精品永久| 免费成人激情视频| 午夜亚洲激情| aaa亚洲精品一二三区| 久久久噜久噜久久综合| 夜夜嗨一区二区| 韩国女主播一区| 国产精品高潮呻吟久久av黑人| 久久精品视频在线看| 亚洲天堂av在线免费观看| 欧美激情第1页| 久久精品国产91精品亚洲| 99国内精品久久| 在线观看一区| 国产女主播一区二区| 欧美激情女人20p| 久久久久久网| 欧美影视一区| 亚洲欧美亚洲| 亚洲图片欧洲图片日韩av| 91久久国产精品91久久性色| 免费成人高清在线视频| 久久国产欧美| 欧美一区二区三区免费大片| 亚洲神马久久| 亚洲视频网站在线观看| 亚洲久久在线| 亚洲人成在线观看一区二区| 国内精品久久久久久久影视蜜臀| 国产精品久久精品日日| 欧美日韩亚洲精品内裤| 欧美久久一区| 欧美日韩二区三区| 欧美老女人xx| 欧美日韩你懂的| 欧美日韩一卡二卡| 欧美日韩在线影院| 欧美日韩精品在线播放| 欧美日本免费| 欧美亚韩一区| 国产精品日韩一区| 国产日韩一级二级三级| 国产精品夜夜嗨| 国产色产综合色产在线视频| 国产日韩一区欧美| 国产无一区二区| 国内精品亚洲| 亚洲大片在线观看| 亚洲国产高清自拍| 亚洲精品免费一二三区| 一本久道久久久| 亚洲综合国产激情另类一区| 亚洲欧美日韩精品久久| 久久9热精品视频| 久久综合九色99| 亚洲承认在线| 一区二区三区免费网站| 亚洲欧美区自拍先锋| 久久激情网站| 欧美极品在线播放| 国产精品白丝黑袜喷水久久久| 国产欧美一区二区精品性色| 一区精品在线播放| 99在线热播精品免费99热| 亚洲欧美日韩国产一区| 久久综合精品国产一区二区三区| 亚洲第一天堂av| 亚洲天堂黄色| 久久免费精品日本久久中文字幕| 欧美激情欧美狂野欧美精品| 国产精品久久久久久久久借妻| 国产真实精品久久二三区| 亚洲第一页在线| 亚洲专区免费| 欧美a级片网站| 亚洲少妇最新在线视频| 久久久亚洲国产天美传媒修理工| 欧美人牲a欧美精品| 国产免费观看久久| 亚洲免费不卡| 久久久视频精品| 亚洲精品中文字幕有码专区| 欧美亚洲在线观看| 欧美伦理在线观看| 韩国成人精品a∨在线观看| 一本色道久久88精品综合| 久久久精品一区| 一区二区三区高清不卡| 久久精品国产一区二区三| 欧美三日本三级少妇三2023| 亚洲福利视频网站| 欧美在线视频观看| 亚洲精品一区二区三区99| 久久久久久久久久久成人| 欧美婷婷在线| 亚洲三级毛片| 免费成人av在线| 亚洲欧美中文日韩v在线观看| 欧美日韩成人一区二区| 亚洲国产精品一区二区三区| 久久超碰97人人做人人爱| 日韩网站在线看片你懂的| 久热精品视频在线观看一区| 国产欧美日本一区二区三区| 中文欧美字幕免费| 亚洲国产高清视频| 久久亚洲精品一区二区| 国产亚洲激情| 亚洲欧美综合精品久久成人| 亚洲三级影片| 男男成人高潮片免费网站| 136国产福利精品导航网址应用 | 久久精品国产96久久久香蕉| 国产精品99久久久久久www| 欧美人牲a欧美精品| 亚洲精品在线一区二区| 欧美激情成人在线| 六月天综合网| 亚洲国产成人一区| 欧美大片一区二区三区| 久久久青草青青国产亚洲免观| 国产一区二区在线观看免费| 欧美在线播放视频| 亚洲欧美制服中文字幕| 国产精品一二三四区| 欧美在线观看视频一区二区三区| 亚洲一区二区三区免费视频| 国产精品美女在线观看| 欧美一级久久久| 久久高清免费观看|