Manish Baphna
Manish Baphna

Reputation: 432

C++ partial template specialization issue with gcc

I am trying to calculate GCD, at compile time using template partial specialization. Following code works fine with clang3.8 but not with gcc7.1. With GCC, it's going into recursive template instantiation without realizing terminating case.

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

Who is behaving sane here?

Upvotes: 1

Views: 130

Answers (1)

max66
max66

Reputation: 66230

If you want to solve the problem, I propose the following improvement

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

If you want to know if is right g++ or clang++, well... I don't know what, exactly, a compiler can or must do in this circumstances so... I don't know.

Precisely, I don't know, when N > M and a compiler encounter,

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

if the compiler must (or can) implement only GCD<N%M, M> or if must (or can) implement GCD<N, M%N> also.

Anyway, if I'm not wrong, clang++ implement only GCD<N%M, M> where g++ implement both.

My improvement is tailored to avoid this problem.

Upvotes: 1

Related Questions