简体   繁体   English

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

[英]How to find HCF of 2 numbers in compile time using template?

I want to calculate HCF of 2 numbers using value of enum with template recursion: 我想使用带有模板递归的枚举值来计算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;
};

which x and y are the 2 numbers,r is the value to test, the principle is that find a number to divide x and y, start from min of x and y, then decrease by 1 until a value of r can divide both x and y. 其中x和y是2个数字,r是要测试的值,原理是找到一个将x和y除的数,从x和y的最小值开始,然后减1直到r的值可以将两个x除和y。 But this code cannot compile because of following errors: 但是由于以下错误,该代码无法编译:

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.

What is the problem? 问题是什么?

@moonshadow's comment is the core answer, but let me expand it into a full answer. @moonshadow的评论是核心答案,但让我将其扩展为完整答案。

The compiler output luckily shows the relevant instantiations: 幸运的是,编译器输出显示了相关的实例化:

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

Let's look at the actual instantiation 让我们看一下实际的实例化

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};
};

Obviously, two things are wrong: 显然,有两件事是错误的:

  1. 3 % 0 is a division by zero 3 % 0是被零除
  2. The instantiation of s<5,3,-1> is unnecessary. s<5,3,-1>的实例化是不必要的。

This is easily fixed with constexpr , but let's stick with a templated solution. 这可以通过constexpr轻松修复,但让我们坚持使用模板化解决方案。 Recursion needs an special case for the end, and HCF(x,y)=1 is that special case for co-primes. 递归最后需要特殊情况,而HCF(x,y)=1是互素的特殊情况。

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

That said, you really should use Euclid's algorithm as this brute-force search won't work for something as easy as s<300,300,300> . 就是说,您确实应该使用Euclid算法,因为这种蛮力搜索无法像s<300,300,300>那样简单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM