2017-06-19 122 views
1

我想在編譯時使用模板部分特化來計算GCD。 以下代碼可以與clang3.8一起使用,但不能與gcc7.1一起使用。使用GCC,它將進入遞歸模板實例化而不會意識到終止情況。gcc的C++部分模板專業化問題

template <int N, int M>                                    
struct GCD{                                       
    static const int value = (N>M)? GCD<N%M, M>::value : GCD<N, M%N>::value;                       
};                                         

template <int M>                                      
struct GCD<0, M>{                                      
    static const int value = M;                                  
};                                         

template <int M>                                      
struct GCD<M, 0>{                                      
    static const int value = M;                                  
};                                         


int main()                                       
{                                          
    static_assert(GCD<12,15>::value == 3, "Error");                               
} 

誰在這裏表現得很健全?

+0

也許只做一個雙參數'GCD'結構的前向聲明,定義在專業化之下。因爲在第一次定義的時候編譯器並不真正瞭解這兩個專業領域。雖然我不知道哪個編譯器是正確的。 –

+0

請注意,在C++ 17中,''標頭中會有['gcd'](http://en.cppreference.com/w/cpp/numeric/gcd)功能。 – InternetAussie

+0

你的數學在這裏不起作用。 –

回答

1

如果要解決這個問題,筆者提出以下改進

template <int N, int M, bool = (M != 0) && (N != 0) && (N > M)> 
struct GCD; 

template <int N, int M> 
struct GCD<N, M, true> 
{ static constexpr int value { GCD<N%M, M>::value }; }; 

template <int N, int M> 
struct GCD<N, M, false> 
{ static constexpr int value { GCD<N, M%N>::value } ; }; 

template <int M> 
struct GCD<0, M, false> 
{ static constexpr int value { M }; }; 

template <int M> 
struct GCD<M, 0, false> 
{ static constexpr int value { M }; }; 

如果你想知道,如果是正確的G ++或鐺++,嗯......我不知道,究竟是什麼,一個編譯器可以或必須在這種情況下做,所以......我不知道。

準確地說,我不知道,當N > M和編譯器相遇,

 static const int value = (N>M)? GCD<N%M, M>::value : GCD<N, M%N>::value;                                                

如果編譯器必須(或可以)只實現GCD<N%M, M>或者如果必須(或可以)實現GCD<N, M%N>也。

無論如何,如果我沒有錯,鏗鏘++只實現GCD<N%M, M>其中g ++實現。

我的改進旨在避免此問題。

+0

你說得對,gcc實現了兩者。 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81134 –