我正在尝试使用模板部分特化在编译时计算GCD。 以下代码适用于clang3.8但不适用于gcc7.1。使用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");
}
谁在这里表现得很清醒?
答案 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 ++或clang ++是对的,那么......我不知道编译器在这种情况下可以或必须做什么,所以...我不知道
确切地说,当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 ++实现两者。
我的改进旨在避免这个问题。