2017-06-19 117 views
1

我想在编译时使用模板部分特化来计算GCD。 以下代码可以与clang3.8一起使用,但不能与gcc7.1一起使用。使用GCC,它将进入递归模板实例化而不会意识到终止情况。gcc的C++部分模板专业化问题

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

也许只做一个双参数'GCD'结构的前向声明,定义在专业化之下。因为在第一次定义的时候编译器并不真正了解这两个专业领域。虽然我不知道哪个编译器是正确的。 –

+0

请注意,在C++ 17中,''标头中会有['gcd'](http://en.cppreference.com/w/cpp/numeric/gcd)功能。 – InternetAussie

+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 ++或铛++,嗯......我不知道,究竟是什么,一个编译器可以或必须在这种情况下做,所以......我不知道。

准确地说,我不知道,当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>也。

无论如何,如果我没有错,铿锵++只实现GCD<N%M, M>其中g ++实现。

我的改进旨在避免此问题。

+0

你说得对,gcc实现了两者。 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81134 –