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};
}*/;
编译结果如下:

C++模板元编程之编译期间“发作从2到某个给定值之间的所有质数”

图中红框标记的输出行,便是15以内的所有质数。


像这样解注释Prime的定义后,可以编译通过,得到的运行结果如下:

/*一个完全特化模板.
**
**注释以后,编译失败,在之后输出的编译错误中,可以找到形如
**...error: incomplete type 'Prime<X,true>' used in ...
**的字段,该字段表示数字X为质数
**
**解注释以后,编译通过,可以输出某个范围内的质数个数
*/
template<int i,bool b>
struct Prime{
	enum{IsPrime=true};
};

C++模板元编程之编译期间“发作从2到某个给定值之间的所有质数”




文章中提到的原始例子在这里:

Primzahlen