1 #ifndef __TABLEAU__
   2 #define __TABLEAU__
   3 
   4 #include <cstdlib>
   5 #include <iostream>
   6 #include <stdexcept>
   7 using namespace std;
   8 
   9 // Un objet-fonction general, a un parametre
  10 template <typename T=float> class Functor1p {
  11 public:
  12     virtual T operator()(T) const = 0;
  13 };
  14 
  15 template <typename T=float> class Tableau {
  16 public:
  17 
  18         // Le constructeur principal - on passe la dimension du tableau en parametre
  19         explicit Tableau(size_t );
  20 
  21         // Le trio infernal
  22         Tableau (const Tableau & );
  23         Tableau & operator=(const Tableau &);
  24         ~Tableau();
  25 
  26         // renvoie la taille du Tableau
  27         size_t size() const { return sz;};
  28         
  29         // renvoie un element du Tableau sans deborder
  30         T & operator[](size_t i);
  31         
  32         // meme chose - version const
  33         T operator[](size_t i) const;
  34         
  35         // operateurs +=
  36         // Le parametre est un autre Tableau
  37         Tableau & operator+=(const Tableau & );
  38         
  39         // Le parametre est un T
  40         Tableau & operator+=(T );
  41         
  42         // imprime le Tableau sur la sortie standard
  43         void print () const;
  44         
  45         // La fonction transform: on leur passe un objet-fonction à 1 paramètre
  46         void transform(const Functor1p<T>& );
  47 
  48 private:
  49         const size_t sz;
  50         T *A;
  51         
  52         // Le signe __ rappelle qu'il s'agit de methodes privees
  53         void __copie (T src, T dest[], size_t s);
  54         void __copie (T src[], T dest[], size_t s);
  55 };
  56 
  57 // Une fonction qui n'est pas une methode
  58 template < typename T> Tableau<T> operator+(const Tableau<T>& t1, const Tableau<T>& t2);
  59 
  60 // Le constructeur principal - on passe la dimension du tableau en parametre
  61 template <typename T> Tableau<T>::Tableau(size_t n): sz(n) {
  62         cerr << "constructeur sz = " << n << '\n';
  63         A = (T *) malloc(sz*sizeof(T));
  64         if ( A == NULL )
  65         {
  66                 throw (bad_alloc());
  67         }
  68         __copie(0.0,A,sz);
  69 };
  70 
  71 // CE QUI SUIT ETAIT JUSQUE LA DANS LE .cpp
  72 
  73 // Le constructeur de copie - on fait l'alloc de memoire puis on copie
  74 template <typename T> Tableau<T>::Tableau (const Tableau<T> & t): sz(t.sz) {
  75         cerr << "constructeur de copie" << '\n';
  76         A = (T *) malloc(sz*sizeof(T));
  77         if ( A == NULL )
  78         {
  79                 throw (bad_alloc());
  80         }
  81         __copie(t.A,A,sz);
  82 };
  83 
  84 // L'operateur = PAS D'ALLOCATION DE MEMOIRE, c'est deja fait !!!
  85 template <typename T> Tableau<T> & Tableau<T>::operator=(const Tableau<T> &t) {
  86         cerr << "operateur =" << '\n';
  87         if (this==&t)    // Pour gerer les cas A=A
  88                 return *this;
  89         
  90         if (sz != t.sz) {
  91                 throw (range_error ("Ne peut pas egaliser deux tableaux de tailles differentes"));
  92         };
  93         __copie(t.A,A,sz);
  94         return *this;
  95 };
  96 
  97 // Le destructeur: rendre la memoire au systeme
  98 template <typename T> Tableau<T>::~Tableau() { 
  99         cerr << "destructeur (sz = " << sz << ")\n";
 100         free(A);
 101 };
 102 
 103 // renvoie un element du tableau sans deborder
 104 template <typename T> T & Tableau<T>::operator[](size_t i) {
 105         if (i>=sz) {
 106                 throw (range_error ( "Debordement de Tableau" ));
 107         } else {
 108                 return A[i];
 109         };
 110 };
 111 
 112 // meme chose - version const
 113 template <typename T> T Tableau<T>::operator[](size_t i) const {
 114         if (i>=sz) {
 115                 throw (range_error ( "Debordement de Tableau" ));
 116         } else {
 117                 return A[i];
 118         };
 119 };
 120 
 121 // operateurs +=
 122 // Le parametre est un autre Tableau
 123 template <typename T> Tableau<T> & Tableau<T>::operator+=(const Tableau<T> & t) {
 124         if (sz != t.sz) {
 125                 throw (range_error ("Ne peut pas egaliser deux tableaux de tailles differentes"));
 126         } else {
 127                 for (size_t i=0; i < sz; i++) {
 128                         A[i] += t[i];
 129                 };
 130         };
 131         return *this;
 132 };
 133 
 134 // Le parametre est un T
 135 template <typename T> Tableau<T> & Tableau<T>::operator+=(T x) {
 136         for (size_t i=0; i < sz; i++) {
 137                 A[i] += x;
 138         };
 139         return *this;
 140 };
 141 
 142 // imprime le Tableau sur la sortie standard
 143 template <typename T> void Tableau<T>::print () const  {
 144         for (size_t i=0; i < sz; 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> void Tableau<T>::__copie (T src, T dest[], size_t s)
 152 {
 153         for ( size_t i=0; i<s; i++) {
 154                 dest[i] = src;
 155         }
 156 }
 157 template <typename T> void Tableau<T>::__copie (T src[], T dest[], size_t s) {
 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> void Tableau<T>::transform(const Functor1p<T>& f ) {
 165         for (int i=0; i< sz; i++) 
 166                 A[i]=f(A[i]);
 167 };
 168 
 169 template <typename T> Tableau<T> operator+(const Tableau<T>& t1, const Tableau<T>& t2) {
 170         Tableau<T> s(t1.size());
 171         if (t1.size() != t2.size()) {
 172                 cerr << "Ne peut pas ajouter deux Tableaux de tailles differentes" << '\n'; 
 173                 exit(1);
 174         } else {
 175                 s = t1;
 176                 s += t2;
 177         };
 178         return s;
 179 };
 180 
 181 
 182 #endif