// version adaptée du programme de Dan Piponi, http://www.sigfpe.com.

// définition des entiers naturels
template<class V> struct Naturel { typedef V valeur; };

// définition de zéro
struct zero
        : public Naturel<zero> { };

// définition d'un sucesseur et d'un prédécesseur d'un entier
template<class C> struct S
        : public Naturel<S<C> > { typedef C predecesseur; };

// noms des entiers jusqu'à 10
typedef S<zero> un;
typedef S<un> deux;
typedef S<deux> trois;
typedef S<trois> quatre;
typedef S<quatre> cinq;
typedef S<cinq> six;
typedef S<six> sept;
typedef S<sept> huit;
typedef S<huit> neuf;
typedef S<neuf> dix;

// définition de l'opération +
template<class C,class D> struct plus
        : public S<plus<C,typename D::predecesseur> > { };

template<class C> struct plus<C,zero>
        : public C { };

// définition de l'opération -
template<class C,class D> struct moins
        : public moins<C,typename D::predecesseur>::predecesseur { };

template<class C> struct moins<C,zero>
        : public C { };

// définition de l'opération x
template<class C,class D> struct fois
        : public plus<C,typename fois<C,typename D::predecesseur>::valeur> { };

template<class C> struct fois<C,zero>
        : public zero { };

// définition de l'opération plus Grand ou Egal
template<class C,class D> struct ge
        : public ge<typename C::predecesseur,typename D::predecesseur> { };

template<class C> struct ge<C,zero>
        : public un { };

template<class C> struct ge<zero,C>
        : public zero { };

template<> struct ge<zero,zero>
        : public un { };

// test de divisibilité
template<class C,class D,class E = S<S<zero> > > struct Divisible { };

template<class C,class D> struct Divisible<C,D,S<S<zero> > >
        : public Divisible<C,D,typename ge<C,D>::valeur> { };

// Cas où C<D
// dans ce cas D divise C si et seulement si C est zéro
template<class C,class D> struct Divisible<C,D,zero>
        : public zero { };

template<class C> struct Divisible<zero,C,zero>
        : public un { };

// Cas où C>=D:
// D divise C si et seulement D divise C-D.
template<class C,class D> struct Divisible<C,D,S<zero> >
        : public Divisible<typename moins<C,D>::valeur,D> { };

// Test de primalité
template<class C,class D = deux,class S = zero,class E = zero,class F =
zero> struct Premier { };

// Nous faisons une boucle allant de deux à l'entier à tester moins 1.

// Sommes nous au bout ?
template<class C,class D> struct Premier<C,D,zero,zero,zero>
        : public Premier<C,D,un,zero,typename ge<D,C>::valeur> { };


// Test la division par D, si pas  de divisibilité alors
// on passe au successeur
template<class C,class D> struct Premier<C,D,un,zero,zero>
        : public Premier<C,S<D>,zero,typename Divisible<C,D>::valeur,zero> { };

// Un facteur à été trouvé, renvoyer zéro
template<class C,class D> struct Premier<C,D,zero,un,zero>
        : public zero { };

// Atteind la fin de la boucle sans avoir trouvé de diviseur.
template<class C,class D> struct Premier<C,D,un,zero,un>
        : public un { };

// écriture d'un nombre en base 10 (c'est plus pratique)
template<class C,class D> struct Decimal
        : public plus<typename fois<dix,C>::valeur,D> { };

//
#include <string>
#include <iostream>
using namespace std;
template<class C> string output(C);
template<> string output(zero) { return "Non"; }
template<> string output(un) { return "Oui"; }

main() {
    // Est-ce que 13 est premier ?
    cout << output(Premier<Decimal<un,trois>::valeur>::valeur()) << endl;
}


