2010-01-28 14 views
2

這是TTL:類型列表運行時typeswitch作爲開關而不是嵌套if?

//////////////////////////////////////////////////////////// 
// run-time type switch 
template <typename L, int N = 0, bool Stop=(N==length<L>::value) > struct type_switch; 

template <typename L, int N, bool Stop> 
    struct type_switch 
    { 
    template< typename F > 
     void operator()(size_t i, F& f) 
     { 
     if(i == N) 
     { 
      f.operator()<typename impl::get<L,N>::type>(); 
     } 
     else 
     { 
      type_switch<L, N+1> next; 
      next(i, f); 
     } 
     } 
    }; 

它用於typeswitching一個類型串。問題是 - 他們通過一系列嵌套的if來做到這一點。有沒有辦法將這種類型的開關做爲單個select語句來代替?

謝謝!

+0

實際使用的這種結構是什麼? – Potatoswatter 2010-01-28 19:47:04

+0

最新的clang可以將這種東西轉換成跳轉表:https://godbolt.org/g/Nco0Al,GCC不能(具有相同的選項):https://godbolt.org/g/4VL9e7。 – user877329 2017-02-11 12:33:03

回答

2

您將需要預處理器來生成一個大的switch。您需要get<>來禁止未綁定的查找。檢查編譯器輸出以確保未使用的情況下不產生輸出,如果你在意的話;根據需要進行調整; v)。

退房了Boost預處理器庫,如果你願意讓擅長這樣的事情......

template <typename L> 
    struct type_switch 
    { 
    template< typename F > 
     void operator()(size_t i, F& f) 
     { 
     switch (i) { 
     #define CASE_N(N) \ 
     case (N): return f.operator()<typename impl::get<L,N>::type>(); 
     CASE_N(0) 
     CASE_N(1) 
     CASE_N(2) 
     CASE_N(3) // ad nauseam. 
     } 
    }; 
+0

如果你去* ad nauseam *,是不是說在某些時候交換機會嘗試實例化一個可能無效N的模板,並且整個事情都無法編譯?遞歸知道哪裏停止,這個開關顯然不是。 (基本上,在我看來,整個開關的想法是完全錯誤的,而不是模板元編程的一種方式。IMO,編譯時開關不過是一個通過遞歸創建的if-chain。) – UncleBens 2010-01-28 20:47:05

+0

@UncleBens:這就是我的意思是「無操作的界外查找」。類型列表模板本身在'get <>'中實現遞歸。它應該檢測到一個超出界限的指數並且什麼都不會返回。至於if鏈的優點,取決於編譯器和應用程序。根據一個重複問題的答案,boost :: variant(一個更廣爲人知的例子)使用了我在這裏概述的技術。 – Potatoswatter 2010-01-28 21:44:59

+0

我只是想在你的回答後兩次詢問幾乎相同的問題而道歉。問題 - 起初我沒有理解你的答案;但現在我明白了,我明白爲什麼我的其他問題是多餘的。 – anon 2010-01-28 22:06:34

0

我不這麼認爲。

這種模板元編程通常是通過遞歸完成的。由於這一切都發生在編譯時,如果沒有運行時遞歸或條件檢查,我不會感到驚訝。

0

你總是可以使用二進制搜索,而不是線性搜索。它會更復雜,更容易出現錯誤(二進制搜索令人驚訝地容易搞砸)。

你也可以手動擴展N type_switch::operator(),其中N是你程序中的類型列表長度數的一些合理的上限。

相關問題