C++のテンプレートで素数計算

C++のテンプレートで計算をするなんて変態だと思っていたのだけど、奥さんがさくっと10分くらいで書いたFizzBuzzのコードを見るとなんか非常に素直で読みやすいコードだったので、僕もテンプレートで何かしてみることにしました。

そんなわけでできたのが素数を求めるコード。途中の「数字を全部出す」と「2の倍数を出す」をコメントで残してあります。isPrime2とかisPrime3とかあるのは3つ合わせてisPrimeの働きをする型のそれぞれの名前を思いつかないので適当な名前になっています。テンプレートにはデフォルトの型引数があるみたいなのでisPrime本体は必要ないですね。

#include <iostream>

using namespace std;
template<int N, int D> struct isPrime2;

template<int N, int D, int R> struct isPrime3{
  isPrime3(){
	// N % D != 0
	// so we should check if N % (D-1) == 0
	isPrime2<N, D-1>();
  }
};

template<int N, int D> struct isPrime3<N, D, 0>{
  isPrime3(){
	// N % D == 0
	// so N is not prime
	// cout << N << " is not prime" << endl;
  }
};


template<int N, int D> struct isPrime2{
  isPrime2(){
	// if N % D == 0?
	isPrime3<N, D, N%D>();
  }
};

template<int N> struct isPrime2<N, 1>{
  isPrime2(){
	// cout << N << " is prime!" << endl;
	cout << N << " ";
  }
};


template<int N> struct isPrime{
  isPrime(){
	isPrime2<N, N-1>();
  }
};



/* ver.2
template<int N, int R> struct isDividable_{
  isDividable_(){
	cout << N << endl;
  }
};

template<int N> struct isDividable_<N, 0>{
  isDividable_(){}
};

template<int N, int M> struct isDividable {
  isDividable(){
	isDividable_<N, N%M>();
  }
};
*/

/* ver.1
template<int N> struct Print {
  Print() {
	cout << N << endl;
  }
};
*/

template<int N> struct Numbers {
  Numbers(){
	Numbers<N-1>();
	// insert visiter here
	/* ver.1
	   Print<N>();
	*/
	/* ver.2
	   isDividable<N, 2>();
	*/
	isPrime<N>();
  }
};

template<> struct Numbers<1> {
  Numbers(){} // empty
};

int main(){
  Numbers<100>();
}

余計なものを取り除いて名前を付け替えてアンタビファイしたやつは↓

#include <iostream>

using namespace std;
template<int N, int D> struct isPrime;

template<int N, int D, int R> struct isPrime_{
  isPrime_(){
    isPrime<N, D-1>();
  }
};

template<int N, int D> struct isPrime_<N, D, 0>{
  isPrime_(){}
};


template<int N, int D=N-1> struct isPrime{
  isPrime(){
    // if N % D == 0?
    isPrime_<N, D, N%D>();
  }
};

template<int N> struct isPrime<N, 1>{
  isPrime(){
    cout << N << " ";
  }
};


template<int N> struct Primes {
  Primes(){
    Primes<N-1>();
    isPrime<N>();
  }
};

template<> struct Primes<1> {
  Primes(){} // empty
};

int main(){
  Primes<100>();
}