2016-05-15 36 views
0

我努力做到以下幾點:錯誤無法接通塊

template <class T> 
void foo(T * ptr){ 
    ...a lot of code ... 
    if(std::is_base_of<Bar<T>,T>::value){ 
     Bar<T> & bar = *ptr; 
     ...a lot of code ... 
    } 
    ...a lot of code  
} 

如果我編譯這個功能有哪些是酒吧的一個子類,一切工作正常,但如果我嘗試用編譯這是沒有,我得到一個錯誤在

Bar<T> & bar = *ptr; 

線。 這是怎麼回事,因爲當T不是Bar<T>的一個子類時,這條線將被執行? 如果這不是通常的做法,我怎麼才能以正確的方式實現這一點?

+0

「未執行」是不一樣的「未編譯」。 –

+1

這是一個模板,編譯器必須爲其生成代碼,即使存在會阻止模板初始化的條件。 – Rakete1111

+0

好的,我明白了。但我怎麼能以正確的方式做到這一點? – Exagon

回答

1

因爲Bar<T>不是T一個子類,

Bar<T> & bar = *ptr; 

這會導致編譯錯誤。這是包含在if()語句中的事實,該語句的計算結果爲false,並且這部分代碼將永遠不會執行,並不會改變這一事實。

這裏的正確方法是專門化模板。

這些方針的東西:

template <class T, bool is_subclass=std::is_base_of<Bar<T>,T>::value> 
void foo(T * ptr); 

template <class T> 
void foo<T, true>(T * ptr){ 
    ...a lot of code ... 

    Bar<T> & bar = *ptr; 
    ...a lot of code ... 

    ...a lot of code  
} 

template <class T> 
void foo<T, false>(T * ptr){ 
    ...a lot of code ... 

    ...a lot of code  
} 

您現在有兩個不同版本的foo模板,一個用於當模板參數是一個子類,它不移動的情況,和一個。

這兩個版本的foo()可能會有大量的通用代碼。因此,您可能需要在這裏做更多的工作,將通用代碼分解爲獨立的模板函數,您將從foo() s中調用。

1

這可以通過多種方式來實現,其中一個例子是標籤調度:

template <class T> 
void bar(T* ptr, std::true_type) 
{ 
    // ...a lot of code ... 
} 

template <class T> 
void bar(T*, std::false_type) 
{ 
    // do nothing 
} 

template <class T> 
void foo(T * ptr){ 
    //...a lot of code ... 
    bar(ptr, std::is_base_of<Bar<T>,T>{}); 
    //...a lot of code  
}