如何使用模板在编译时找到2个数字的HCF?

时间:2016-04-28 10:12:01

标签: c++ templates math

我想使用带有模板递归的枚举值来计算2个数字的HCF:

#include <stdio.h>
template<int x,int y,int r>
struct s{
    enum{e=x%r==0 && y%r==0?r:s<x,y,r-1>::e};
};

int main(){
    printf("%d\n",s<3,5,MIN(3,5)>::e);
    return 0;
};

其中x和y是2个数,r是要测试的值,原理是找到一个数字来划分x和y,从x和y的min开始,然后减1,直到r的值可以将x和y分开。但是由于以下错误,此代码无法编译:

xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -252>'     requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -251>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -250>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -249>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -248>' requested here
xxx.cpp:4:31: note: (skipping 246 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -1>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, 0>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, 1>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, 2>' requested here
xxx.cpp:8:19: note: in instantiation of template class 's<3, 5, 3>' requested here
printf("%d\n",s<3,5,3>::e);
              ^
xxx.cpp:4:31: note: use -ftemplate-depth=N to increase recursive template instantiation depth
enum{e=x%r==0 && y%r==0?r:s<x,y,r-1>::e};
                          ^
1 error generated.

有什么问题?

1 个答案:

答案 0 :(得分:1)

@ moonshadow的评论是核心答案,但让我把它扩展为一个完整的答案。

编译器输出幸运地显示了相关的实例:

xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, -1>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, 0>' requested here
xxx.cpp:4:31: note: in instantiation of template class 's<3, 5, 1>' requested here

让我们看一下实际的实例化

template<int x = 3, int y = 5, int r = 0>
struct s{
    enum{e = 3%0==0 && 5%0==0 ? 0 : s<5,3,-1>::e};
};

显然,有两件事是错的:

  1. 3 % 0是零除
  2. s<5,3,-1>的实例化是不必要的。
  3. 使用constexpr可以很容易地解决这个问题,但让我们坚持使用模板解决方案。递归需要一个特殊情况,HCF(x,y)=1是共同素数的特例。

    template <int x, int y> 
    struct s<x,y,1> { enum e = 1 };
    

    那就是说,你真的应该使用Euclid's algorithm,因为这种蛮力搜索不会像s<300,300,300>那样简单。