2017-06-19 7 views
1

Ich versuche, GCD zu kompilieren Zeit mit Vorlage teilweise Spezialisierung zu berechnen. Der folgende Code funktioniert gut mit clang3.8, aber nicht mit gcc7.1. Mit GCC geht es in rekursive Template-Instanziierung, ohne Abschlussfall zu realisieren.C++ partielle Vorlage Spezialisierung Problem mit gcc

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");                               
} 

Wer verhält sich hier vernünftig?

+0

Vielleicht nur eine Vorwärtsdeklaration der Zwei-Argument 'GCD' Struktur, mit der Definition unterhalb der Spezialisierungen. Denn zum Zeitpunkt der ersten Definition weiß der Compiler nichts über die beiden Spezialisierungen. Welcher Compiler korrekt ist, weiß ich nicht. –

+0

Beachten Sie, dass es in C++ 17 eine '' gcd''- (http://en.cppreference.com/w/cpp/numeric/gcd) Funktion im Header ' 'gibt. – InternetAussie

+0

Und deine Mathematik funktioniert hier nicht. –

Antwort

1

Wenn Sie das Problem lösen wollen, schlage ich folgende Verbesserung

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 }; }; 

Wenn Sie wollen wissen, ob das Richtige g ++ oder Klirren ++, na ja ... ich weiß nicht, was genau ein Compiler kann oder muss unter diesen Umständen tun ... Ich weiß es nicht.

Genau, ich weiß nicht, wenn N > M und eine Compiler Begegnung,

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

wenn der Compiler muss (oder kann) implementieren nur GCD<N%M, M> oder muss (oder kann) implementieren GCD<N, M%N> auch.

Wie auch immer, wenn ich nicht falsch liege, clang ++ implementieren nur GCD<N%M, M> wo g ++ beide implementieren.

Meine Verbesserung ist zugeschnitten, um dieses Problem zu vermeiden.

+0

Sie haben Recht, gcc implementiert beides. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81134 –

Verwandte Themen