sizeof 感知過載,模板具現, 轉換規則

2021-07-25 18:24:12 字數 3068 閱讀 1346

問題:如何偵知任意型別 t 是否可以自動轉換為型別 u?

方案:偵測轉換能力的想法:合併運用 sizeof 和過載函式。

1 依賴 sizeof,sizeof 有著驚人的能力,你可以把 sizeof  用在任何表示式身上,不論後者有多複雜。sizeof 會直接傳回大小,不需拖到執行期才評估。這意味著 sizeof 可以感知過載 (overloading)、模板具現(template instantiation)、轉換規則(conversion rules)、或任何可發生於c++ 表示式身上的機制。

sizeof  的其他用法可參考:

2 提供兩個過載函式:其中乙個接受 u(u 型別代表目前討論中的轉換目標)。另乙個接受 」任何其他型別「。以型別 t 的暫時物件來呼叫過載函式,t 是否可轉換成 u 正式我們要驗證的。如果接受 u的那個函式被呼叫,我們就知道 t 可轉換為 u;否則 t便無法轉換為 u。為了知道哪乙個函式被呼叫,兩個過載函式的返回不同的返回型別,並以 sizeof 來區分其大小。型別本身無關緊要,重要的是其大小必須不同。

[cpp] view plain copy

01.// 最簡單區分返回值大小的方法 

02.typedef char small; 

03.class big ;  

04.// 宣告兩個過載函式  

05.small test(u); 

06.big test(...); // 呼叫乙個帶省略符的函式,可接受任何型別的引數,編譯器優先選擇最準確的過載函式,所以這當然是最差的選擇 

07. 

08.// 這裡呼叫 t() 的預設建構函式 

09.const bool convexists = sizeof (test(t())) == sizeof(small); // sizeof 會在編譯器求得函式返回值的大小,但不會執行該函式體 

10.// 如果 t 型別的預設構造為 private,可以構造乙個 t maket();  

11.const bool convexists = sizeof (test(maket())) == sizeof(small); 

當然,我們可以用 class template 包裝,隱藏 型別推到的細節:

[cpp] view plain copy

01.template

02.class conversion 

03.; 

06.    static small test(u);         // 很顯然這裡只能定義靜態成員函式,否則下面 enum中 existes表示式中 sizeof 只能評估呼叫靜態的成員函式,而普通的成員函式的呼叫依賴於類的例項物件。 

07.    static big test(...); 

08.    static t maket(); 

09.public: 

10.        // exists 值為 true 時,t 可轉換為型別 u 

11.    enum ; 

12.        // exist2way 表示 t 和 u 之間是否可以雙向轉換。例如 int和 double 可以雙向轉換 

13.    enum ; 

14.        // 如果 t 和 u 是相同的型別, 這個值便為true 

15.    enum ; 

16.}; 

17.可以通過偏特化來實現sametype 

18.template

19.class conversion < t, t > 

20.; 

23.}; 

有了 conversion 的幫助,可以定義巨集來簡化判斷繼承關係:

[cpp] view plain copy

01.#define supersubclass(t, u) \ 

02.    (conversion::exists && \ 

03.    !conversion::sametype) 

如果 u 是public 繼承於 t,或 t 或 u 是同一型別,那麼 supersubclass(t, u) 會傳回 true。

當 supersubclass(t, u) 對 const u* 和 const t* 作「可轉換」評估時,只有三種情況下 const u* 可以隱式轉換為 const t*:

1 t 和 u是同一種型別

2 t 是 u 的乙個 unambiguous (不模稜兩可的、非歧義的) public base。

3 t 是 void。

第三種情況可以再第二次測試中解決掉。更嚴謹的測試:

[cpp] view plain copy

01.#define supersubclass_strict(t, u) \ 

02.    (supersubclass(t, u) && \ 

03.    !conversion::sametype) 

為何這些**都加上 const 修飾?原因是我們不希望因 const 而導致轉型失敗。 如果 template **實施 const 兩次(對乙個已經是 const 的型別而言),第二個 const 會被忽略。在 supersubclass 中使用 const,更安全些。

supersubclass 很明顯告訴使用者 判斷 t 是否是 u 的父類。

測試:[cpp] view plain copy

01.class super{}; 

02.class sub :public super {}; 

03.int main() 

04.{ 

05.    cout << conversion::exists << ' ' 

06.        << conversion::exists << ' ' 

07.        << conversion>::exists << endl; 

08.    bool bflag = supersubclass(super, sub); 

09.    bflag = supersubclass_strict(super, sub); 

10. 

11.return 0; 

過載模板函式

include using namespace std 求兩個int值的最大值 inline int const max int const a,int const b 求兩個任意型別值中的最大者 template inline t const max t const a,t const b int...

C 模板過載

產生背景 需要多個對不同型別使用同一種演算法函式時可以使用模板,但是並非所有的型別都使用同一種演算法,為了解決這個問題,產生了模板過載。tips 1.如同函式的過載一樣,模板過載函式的特徵標必須不同 2.並非所有的模板引數都必須是模板引數型別 顯示具體化 explicit specializatio...

模板和過載

1.過載函式,其實也很好理解。什麼是過載函式呢?就是共用同一函式名。在共用中得注意的事項 1 函式名相同但是函式的形參型別名不同或者是形參的個數不同。2 在宣告形參的時候,如果在函式中,宣告了乙個形參是const限定的,在實參中,應該說是對應的,其實const 限定的可以傳遞給const限定的形參,...