fra0  | Code :
 - // THE QuiCK N' DIRTY TEMPLATE SURVIVAL KIT 
 - // oublies tout , le compilateur C++ moderne
 - // il copie, il colle, il cherche, il remplace,ton code comme une dactylo déchainée
 - // les templates ils te grondent si tu fais des bêtises
 - // sinon ils font le travail de 50 ingénieurs allemands sous exta.
 - // la définition canonique est assez simple
 - template <class Noyau> struct Point
 - {
 - 	Noyau x,y,z;
 - 	Point(Noyau _x=0,Noyau _y=0,Noyau _z=0):x(_x),y(_y),z(_z) {}
 - };
 - // l'instanciation aussi
 - Point<double> origine;
 - /* // qui remplace simplement "Noyau" par "double" et produit un imaginaire :
 - struct __Point
 - {
 - 	double x,y,z;
 - 	__Point(double _x=0,double _y=0,double _z=0):x(_x),y(_y),z(_z) {}
 - };
 - 
 - __Point origine; */
 - // c'est déjà très pratique on peut écrire
 - typedef Point<unsigned char> Couleur;
 - const Couleur jaune(255,240,0);
 - // après on peut très bien fournir des paramètres par défaut
 - template <class Noyau=float> struct Point
 - {
 - 	Noyau x,y,z;
 - 	Point(Noyau _x=0.0f,Noyau _y=0.0f,Noyau _z=0.0f):x(_x),y(_y),z(_z) {}
 - };
 - // qui permet des instanciations du genre
 - Point<> bar;
 - // les templates ne sont pas difficiles sur le nombre de paramètres et gèrent la précédence
 - template <class Noyau=double,class Bool=bool,Bool checkBounds=true> struct Point
 - {
 - 	Noyau x,y,z;
 - 	Point(Noyau _x=0.0f,Noyau _y=0.0f,Noyau _z=0.0f):x(_x),y(_y),z(_z)
 - 	{
 -   if(checkBounds)
 -   {
 -   	/* etc */
 -   }
 - 	}
 - };
 - // les typedef prennent déjà une autre tournure...
 - typedef Point<long double,bool,true> Point_Managed;
 - typedef Point<float,size_t,false> Point_Savage;
 - // ça reste un pré-processeur on peut très bien écrire
 - template<int Major=0,int Minor=0,int Release=0,int Buid=-1> struct Version
 - {
 - 	void get(std::ostream&o)
 -         {
 -              o<<"v"<<Major<<'.'<<Minor<<'.'<<Release<<'.'<<Buid<<std::endl;
 -         }
 - };
 - static Version<0,2> version;
 - // aucun stockage superflu, ça marche récursivement aussi
 - Point<Point<int> > bar;
 - /* // qui correspond à peu près à ça
 - struct __Point
 - {
 - 	struct  
 - 	{
 - 	    int x,y,z;
 - 	} __Point_;
 - 
 - 	__Point_ x,y,z;
 - };
 - 
 - __Point bar;
 - */
 - // les appels suivants sont ok
 - bar.x.y=0;
 - bar.z=Point<int>(7,-1,-1);
 - // en fait le compilateur ne vérifie le code que quand c'est nécessaire, on peut écrire directement
 -     template <class Objet,class Param> struct Executable
 -     {
 -         Objet o;
 -        
 -       //   Executable(const Objet&_o):o(_o){}
 -              
 -         void operator()(const Param ¶m1=-1)
 -         {
 -             o.Go(param1);
 -         }
 -     };
 -    
 -     // sans rien connaitre de Objet ou de Param, cepedant seules les classes avec une méthode Go (et les bons paramètres) seront acceptées si ton code appelle l'opérateur () de Executable
 -    
 -     struct Foo
 -     {
 -         void Go(std::string name)
 -         {
 -             std::cout<<"Foo::"<<name<<" fait son truc"<<std::endl;
 -         }
 -     };
 -    
 -     class Bar
 -     {
 -         // du blabla
 -        
 -         public :
 -        
 -            // ...
 -    
 -         void Go(int id)
 -         {
 -             std::cout<<"un Bar fait le truc n°"<<id<<std::endl;
 -         }
 -     };
 -    
 - // puis quelque part dans le code
 -    
 -     Executable<Foo,std::string> commande;
 -    
 -     // blablah
 -    
 -     commande("Hello" );
 -    
 -     // ou directement
 -    
 -     Executable<Bar,int>()(0x12345678);
 - }
 - // si les types sont connus à l'avance ça offre une alternative simple et efficace à l'héritage  
 - // où tout est mis à plat avant l'exécution... tu dois maintenant comprendre ça :
 - template<int count> class unrolled_loop
 - {
 -   public:
 -     unrolled_loop()
 -     {
 -             unrolled_loop<count-1>();
 -             std::cout <<"item #"<< count << std::endl;           
 -     }
 - };
 - // ça prend tout son sens avec une spécialisation, la cerise sur le gâteau des templates :
 - template <> class unrolled_loop<0>{};
 - // ça arrête d'appeller récursivement le constructeur de unrolled_loop<count-1> pour le cas où count-1==0
 - // à partir de la, il n'y a plus que les instructions std::cout <<"item #"... à ajouter au fichier objet/binaire.
 - unrolled_loop<1024> scan_line; // 1024 tests & incréments économisés
 - // yeah !!
 
  |  
    Message édité par fra0 le 13-01-2006 à 06:44:29
  |