1 #ifndef __TABLEAU__
   2 #define __TABLEAU__
   3 
   4 #include <cstdlib>
   5 #include <iostream>
   6 using namespace std;
   7 
   8 // Un objet-fonction general, a un parametre
   9 template <typename T=float> class Functor1p {
  10 public:
  11     virtual T operator()(T) const = 0;
  12 };
  13 
  14 template <typename T=float, size_t S=100> class Tableau {
  15 public:
  16 
  17         // Le constructeur principal
  18         explicit Tableau();
  19         
  20         // Le trio infernal
  21         Tableau (const Tableau & );
  22         Tableau & operator=(const Tableau &);
  23         ~Tableau();
  24 
  25         // Le constructeur de conversion
  26         template <typename U> Tableau (const Tableau<U,S>&);
  27 
  28         // renvoie la taille du Tableau
  29         size_t size() const { return S;};
  30         
  31         // renvoie un element du Tableau sans deborder
  32         T & operator[](size_t i);
  33         
  34         // meme chose - version const
  35         T operator[](size_t i) const;
  36         
  37         // operateurs +=
  38         // Le parametre est un autre Tableau
  39         Tableau & operator+=(const Tableau & );
  40         
  41         // Le parametre est un T
  42         Tableau & operator+=(T );
  43         
  44         // imprime le Tableau sur la sortie standard
  45         void print () const;
  46         
  47         // La fonction transform: on leur passe un objet-fonction à 1 paramètre
  48         void transform(const Functor1p<T>& );
  49         
  50 
  51 private:
  52         T A[S];
  53         
  54         // Le signe __ rappelle qu'il s'agit de methodes privees
  55         void __copie (T src, T dest[]);
  56         void __copie (T src[], T dest[]);
  57 };
  58 
  59 // Une fonction qui n'est pas une methode
  60 template < typename T,size_t S> Tableau<T, S> operator+(const Tableau<T, S>& t1, const Tableau<T, S>& t2);
  61 
  62 // Le constructeur principal - pas d'allocation memoire a faire !
  63 template <typename T,size_t S> Tableau<T, S>::Tableau() {
  64         cerr << "constructeur sz = " <<  S << '\n';
  65         __copie(0.0,A);
  66 };
  67 
  68 // CE QUI SUIT ETAIT JUSQUE LA DANS LE .cpp
  69 
  70 // Le constructeur de copie - pas d'allocation memoire a faire !
  71 template <typename T,size_t S> Tableau<T, S>::Tableau (const Tableau<T, S> & t) {
  72         cerr << "constructeur de copie" << '\n';
  73         __copie(t.A,A);
  74 };
  75 
  76 template <typename T,size_t S> template <typename U> Tableau<T,S>::Tableau (const Tableau<U,S>& t) {
  77         //__copie(t.A,A); // Ne compile pas car t.A est PRIVATE
  78         for (size_t i=0; i<S; ++i) {
  79                 A[i] = t[i];
  80         }
  81 }
  82 
  83 // L'operateur = PAS D'ALLOCATION DE MEMOIRE, juste gerer les identites
  84 template <typename T, size_t S> Tableau<T, S> & Tableau<T, S>::operator=(const Tableau<T, S> &t) {
  85         cerr << "operateur =" << '\n';
  86         if (this==&t)    // Pour gerer les cas A=A
  87                 return *this;
  88         __copie(t.A,A);
  89         return *this;
  90 };
  91 
  92 // Le destructeur: PAS NECESSAIRE ICI
  93 template <typename T, size_t S> Tableau<T,S>::~Tableau() { 
  94         cerr << "destructeur (sz = " << S << ")\n";
  95 };
  96 
  97 // renvoie un element du tableau sans deborder
  98 // pas la peine de tester i < 0, size_t est un type unsigned
  99 // (decommentez ce qui suit vous verrez si cela compile)
 100 template <typename T,size_t S> T & Tableau<T, S>::operator[](size_t i) {
 101         //if (i<0) {
 102         //  cerr << "ATTENTION Debordement de tableau - je renvoie tableau[0]\n";
 103         //  return *A;
 104         //} else
 105         if (i>= S) {
 106                 cerr << "ATTENTION Debordement de Tableau - je renvoie Tableau[sz-1]\n";
 107                 return A[S-1];
 108                 // return *(A+sz-1);  // Une autre manière d'écrire la même chose
 109         } else {
 110                 return A[i];
 111                 //return *(A+i);
 112         };
 113 };
 114 
 115 // meme chose - version const
 116 template <typename T, size_t S> T Tableau<T, S>::operator[](size_t i) const {
 117         if (i>= S) {
 118                 cerr << "ATTENTION Debordement de Tableau - je renvoie Tableau[sz-1]\n";
 119                 return A[S-1];
 120         } else {
 121                 return A[i];
 122         };
 123 };
 124 
 125 // operateurs +=
 126 // Le parametre est un autre Tableau
 127 template <typename T,size_t S> Tableau<T, S> & Tableau<T, S>::operator+=(const Tableau<T, S> & t) {
 128         for (size_t i=0; i <  S; i++) {
 129                 A[i] += t[i];
 130         };
 131         return *this;
 132 };
 133 
 134 // Le parametre est un T
 135 template <typename T,size_t S> Tableau<T, S> & Tableau<T, S>::operator+=(T x) {
 136         for (size_t i=0; i <  S; i++) {
 137                 A[i] += x;
 138         };
 139         return *this;
 140 };
 141 
 142 // imprime le Tableau sur la sortie standard
 143 template <typename T,size_t S> void Tableau<T, S>::print () const  {
 144         for (size_t i=0; i < S; i++) {
 145                 cout << A[i] << " ";
 146         };
 147         cout << '\n';
 148 }
 149 
 150 // copie l'entier src dans la zone memoire pointee par dest
 151 template <typename T,size_t S> void Tableau<T, S>::__copie (T src, T dest[])
 152 {
 153         for ( size_t i=0; i< S; i++) {
 154                 dest[i] = src;
 155         }
 156 }
 157 template <typename T,size_t S> void Tableau<T, S>::__copie (T src[], T dest[]) {
 158         for (size_t i=0; i< S; i++) {
 159                 dest[i] = src[i];
 160         };
 161 }
 162 
 163 // La famille de fonction transform: on lui passe un objet-fonction derive de Functor1p
 164 template <typename T,size_t S> void Tableau<T, S>::transform(const Functor1p<T>& f ) {
 165         for (int i=0; i<  S; i++) 
 166                 A[i]=f(A[i]);
 167 };
 168 
 169 template <typename T,size_t S> Tableau<T, S> operator+(const Tableau<T, S>& t1, const Tableau<T, S>& t2) {
 170         Tableau<T,S> s;
 171         s = t1;
 172         s += t2;
 173         return s;
 174 };
 175 
 176 #endif