2015-08-25 77 views
0

類似變體的類型通常通過模擬Vtables來實現,參見例如。現在類似變體的類型:爲什麼是vtable?

https://www.youtube.com/watch?v=uii2AfiMA0o

,作爲替代,一個能夠簡單地使用switch聲明。

問題:如果variant應該是一個模板,即如果可能類型的數量未知,是否有任何理由更喜歡一個vtable到switch語句,而不是switch語句變得困難的事實?

不同的陳述:是否有任何理由做下列事情,而不是在apply函數中使用switch語句?

#include <iostream> 
using namespace std; 

enum TypeTag { typeInt = 0, typeDouble = 1, typeChar = 2 }; 

struct Variant { 
    TypeTag tag; 
    union { int i; double d; char c; }; 
}; 

template <class F> 
void apply (Variant const & v, F f) { 
    struct Helper { 
     static void callInt (Variant const & v, F f) { f.callInt (v.i); } 
     static void callDouble (Variant const & v, F f) { f.callDouble (v.d); } 
     static void callChar (Variant const & v, F f) { f.callChar (v.c); } 
    }; 
    using hp = void (*) (Variant const & v, F f); 
    static constexpr hp vtable [3] = { 
     &Helper::callInt, &Helper::callDouble, &Helper::callChar 
    }; 
    (vtable [v.tag]) (v, f); 
} 


int main() { 
    struct { 
     void callInt (int) const { std::cout << "Int\n"; } 
     void callDouble (double) const { std::cout << "Double\n"; } 
     void callChar (char) const { std::cout << "Char\n"; } 
    } multifunction; 
    Variant v; 
    v.tag = typeDouble; v.d = 2.0; 
    apply (v, multifunction); 
    return 0; 
} 

回答

1

換一種說法:沒有任何理由這樣做下面的,而不是在應用函數使用switch語句?

我沒有看到使用這兩種方法的程序集看起來(寬泛地)爲apply函數的程序會有什麼不同。在這兩種情況下,你基本上都會有一個基於v.tag的值的跳轉表,並立即調用相應的函數,然後返回。

我會假設開關版本對編譯器來說會稍微透明,因爲它不會涉及通過函數指針的間接尋址。所以開關版本最終可能因爲這個原因而變得更快。

我認爲支持vtable方法的主要原因是,如果您想要基於C++ 11 variadic模板創建模板變體類,則可能更容易實現vtable方法,因爲我認爲使用模板來合成switch語句很困難。 (至少,我不知道該怎麼做,想了一下之後。)

+0

我編輯了代碼並修復了'typeChar = 3'的錯誤。 – JohnB

+0

同樣,在2017年,動態 - >靜態調度庫可用,例如, (https://github.com/jacquelinekay/petra) – xtofl