我正在尝试计算 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");
}
谁在这里表现得理智?
最佳答案
如果要解决问题,我提出以下改进
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++ 实现了两者。
我的改进是为了避免这个问题。
关于gcc 的 C++ 部分模板特化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44627448/