C++模板元编程之编译期间“发作从2到某个给定值之间的所有质数”
C++模板元编程之编译期间“产生从2到某个给定值之间的所有质数”
本文的灵感来自于C++模板元编程技术与应用,里面讲到“
1994年,在圣迭哥举行的一次C++标准委员会会议期间,
Erwin Unruh展示了一段特别的代码,可以在编译期以编译
错误信息的方式产生从2到某个给定值之间的所有质数。
”
所以自己用一下午的时间做了一个实现,代码如下:
#include <iostream> using namespace std; /*声明一个质数检查器模板 ** **i :需要被检查的数字 **factor :正在用于测试i的因数 **isPrime :之前的测试是否通过,即在测试factor之前,i是否是质数 */ template<int i,int factor,bool isPrime> struct PrimeChecker; template<int i,int factor> struct PrimeChecker<i,factor,true>{ enum{Result=PrimeChecker<i,factor-1,i%factor!=0>::Result}; }; template<int i,int factor> struct PrimeChecker<i,factor,false>{ enum{Result=false}; }; template<int i> struct PrimeChecker<i,2,true>{ enum{Result=(i==2||i%2!=0)}; }; template<int i> struct PrimeChecker<i,1,true>{ enum{Result=true}; }; /*一个完全特化模板. ** **注释以后,编译失败,在之后输出的编译错误中,可以找到形如 **...error: incomplete type 'Prime<X,true>' used in ... **的字段,该字段表示数字X为质数 ** **解注释以后,编译通过,可以输出某个范围内的质数个数 */ template<int i,bool b> struct Prime{ enum{IsPrime=true}; }; template<int i> struct Prime<i,false>{ enum{IsPrime=false}; }; //用于枚举小于i的质数 template<int i> struct EnumPrime{ enum{PrimeCount=(Prime<i,PrimeChecker<i,i-1,true>::Result>::IsPrime?1:0) +EnumPrime<i-1>::PrimeCount}; }; /*一个完全特化的类模板 **其实可以直接让PrimeCount=1的 **,但是为了"使用编译期间的错误信息打印质数" **,还是使用了一个等价的Prime模板 */ template<> struct EnumPrime<2>{ enum{PrimeCount=(Prime<2,true>::IsPrime?1:0)}; }; int main(){ //用于编译期间测试某个数是不是质数.如果是,运行时输出1;否则输出0 cout<<PrimeChecker<4,3,true>::Result<<endl; //用于编译期间计算小于某个数的质数个数 cout<<EnumPrime<15>::PrimeCount<<endl; }
像这样注释掉Prime的定义:
/*一个完全特化模板. ** **注释以后,编译失败,在之后输出的编译错误中,可以找到形如 **...error: incomplete type 'Prime<X,true>' used in ... **的字段,该字段表示数字X为质数 ** **解注释以后,编译通过,可以输出某个范围内的质数个数 */ template<int i,bool b> struct Prime/*{ enum{IsPrime=true}; }*/;编译结果如下:
图中红框标记的输出行,便是15以内的所有质数。
像这样解注释Prime的定义后,可以编译通过,得到的运行结果如下:
/*一个完全特化模板. ** **注释以后,编译失败,在之后输出的编译错误中,可以找到形如 **...error: incomplete type 'Prime<X,true>' used in ... **的字段,该字段表示数字X为质数 ** **解注释以后,编译通过,可以输出某个范围内的质数个数 */ template<int i,bool b> struct Prime{ enum{IsPrime=true}; };
文章中提到的原始例子在这里:
Primzahlen