2017-06-19 11 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

恐らく、2つの引数をとる 'GCD'構造体の前方宣言だけを行います。最初の定義の時点でコンパイラは2つの特殊化について実際には分かっていないためです。どのコンパイラが正しいのか分かりません。 –

+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 ++または打ち鳴らす++であるかどうかを知りたい場合は、よく...私は何を知っていない、Aコンパイラはこのような状況で行うことができる、またはそうする必要があります...私は分かりません。 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>を実装しています。

とにかく、私が間違っていないと、clang ++はGCD<N%M, M>を実装しています。ここでg ++は両方を実装しています。

私の改善はこの問題を避けるために調整されています。

+0

あなたは正しいです、gccは両方を実装しています。 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81134 –

関連する問題