2013-06-21 475 views
3

我有一個簡單的矩陣類,看起來像這樣啓用功能:根據模板類變量

template <int m, int n> 
class matrix { 
public: 
    std::enable_if<std::is_same<matrix, matrix<4,4>>::value, void> 
    translate(float x, float y, float z) { 
     // Do stuff 
    } 

private: 
    float mat[m * n]; 
}; 

我預計std::enable_if使功能僅當我實例化一個matrix<4,4>,但現在看來,這就是錯誤。

int main() { 
    matrix<4, 3> mat3; 
    mat3.translate(1.0f, 1.0f, 1.0f); 

    return 0; 
} 

上面的代碼編譯沒有錯誤。我究竟做錯了什麼?

我知道我可以簡單地把static_assert(m == 4 && n == 4)放在函數體中,但我正在尋找一個更乾淨的解決方案,並希望在過程中學習一些關於模板的知識。

+0

您可以使用'#ifdef'和其他C預處理器去除或添加功能,具體取決於模板參數 – dchhetri

+0

@ user814628:嗯,不,你不能。預處理在模板擴展之前發生。 –

+0

你是對的,我只是在做白日夢... – dchhetri

回答

6

用於起動器,你應該這樣做:

typename std::enable_if<std::is_same<matrix, matrix<4,4>>::value, void>::type 

而不只是:

std::enable_if<std::is_same<matrix, matrix<4,4>>::value, void> 

但這樣做還是不行,因爲條件將在類模板實例化時進行評估,因此即使您從未致電translate()也會產生錯誤。

如果你可以使用C++ 11,你可以做到以下幾點:

template<typename T = matrix> 
typename std::enable_if< 
    std::is_same<T, matrix<4,4>>::value> 
    ::type 
translate(float x, float y, float z) { 
    // Do stuff 
} 

這裏是一個live example。請注意,編譯錯誤是如何通過調用translate()而不是僅僅通過matrix<4,3>的實例觸發的。

0

您可以在參數enable_if中使用& &和==。此外,您忘記了:: type,它是僅當條件爲真時才存在的成員(並且啓用也是如此)。這也需要添加一個類型名稱。這裏是工作的代碼:

#include <type_traits> 

template <int m, int n> 
class matrix { 
public: 
    typename std::enable_if<m == 4 && n == 4, void>::type 
    translate(float x, float y, float z) { 
     // Do stuff 
    } 

private: 
    float mat[m * n]; 
}; 

int main() { 
    // Compile fine 
    matrix<4, 4> mat4; 
    mat4.translate(1.0f, 1.0f, 1.0f); 

    // Compile error 
    matrix<4, 3> mat3; 
    mat3.translate(1.0f, 1.0f, 1.0f); 

    return 0; 
} 
+0

但是,當你實例化這個類時,這會導致編譯錯誤,而不是當你調用'translate()' –

+0

這樣也行不通...... SFINAE只適用於模板/模板函數。在這種情況下,您正在嘗試將SFINAE應用於本身是模板一部分的非模板函數。您需要將該功能本身作爲模板。 –

+0

嗯,你說得對 – bennofs