C++ 編譯期怎麼判斷一個類是不是純虛類,我有一段代碼,可以達到效果,但不知道為什麼這麼寫?

定義:

template &
struct IsAbstract
{
typedef char SmallType;
typedef int LargeType;

template &
static char Test(U(*)[1]);
template &
static int Test(...);

const static bool Result = sizeof(Test&(NULL)) == sizeof(LargeType);
};

使用:

IsAbstract&::Result 就是T類是不是純虛類的bool值.

補充:

我大概知道它是利用了 純虛類 和 普通類 的成員函數指針大小不同來判斷的,但為什麼這樣寫可以判斷,原理是什麼,那兩 Test 函數又為什麼寫成那樣呢?

請大神賜教。


這是利用了Substitution failure is not an error原則,有重載的函數匹配模板參數時如果不成功並不算編譯錯誤,會繼續嘗試對其它的重載進行匹配。

這個trait的邏輯很簡單,判斷Test&(NULL)的返回值類型,也就是判斷具體匹配了哪個重載。

當T為抽象類的時候

template &
static char Test(U(*)[1]);

不能匹配成功。因為這裡的參數是指向U數組的指針,數組要求類型不能是reference(引用), void(空), function(函數)和abstract(抽象)。此處失敗後

template &
static int Test(...);

可以匹配成功,因為...匹配任意參數。

所以T是抽象類時Test&(NULL)的類型是int,否則是char。

這個Test寫法可以這樣考慮。

首先能想到寫法是直接使用對象或對象數組

template &
static char Test(U u[1]);

為了調用這個函數你需要創建一個對象,但是對於抽象類在編譯期間會失敗。

然後考慮指針

template &
static char Test(U* u);

這種寫法的好處是我們不用創建對象,可以使用空指針作為參數。但抽象類的指針是合法的,所以不管是什麼類型都能匹配成功。

那麼把兩種寫法結合起來就是題中的寫法,既使用了數組類型限定了可以匹配的類型,又可以使用空指針去匹配。


sfinae 。

http://en.cppreference.com/w/cpp/language/sfinae

參見其中 type sfinae 部分。


參見pongba的type_traits說明

boost源碼剖析之:泛型編程精靈type_traits(rev#2)


推薦閱讀:

操作系統有什麼自相矛盾的地方?
Linux 下的伺服器時間同步方案有哪些?
Linux, emacs難以割捨的情結,單位使用的是win + vs,怎麼辦?
Linux下C/C++動態庫在運行時是怎樣載入進來的?
為什麼 Linux 沒有註冊表?為什麼說註冊表是萬惡之源?

TAG:編程 | Linux | C編程語言 | CC |