Reputation: 432
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
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