Partage
  • Partager sur Facebook
  • Partager sur Twitter

Classe std::vector

Copie de celle-ci ^^

Sujet résolu
Anonyme
    5 juillet 2007 à 11:53:44

    Bonjour à tous :) .

    Après std::string, je m'attaque aujourd'hui à std::vector...
    J'ouvre ce topic afin de pouvoir poser mes questions, car je sens qu'elles vont être nombreuses ^^ .

    On commence tout de suite avec un problème de template, avec les itérateurs.
    J'ai donc une classe template vector, qui comporte en class publique une classe iterator.
    Mon problème est lorsque je veux faire renvoyer un iterator par une méthode de vector<T>::iterator.

    Je vous passe une bonne partie de mon code, je ne le mettrai en entier pour vous demander votre avis que lorsqu'il fonctionnera :p .

    vector.h
    #ifndef DEF_VECTOR
    #define DEF_VECTOR

    namespace myStl
    {

        template <typename T>
        class vector
        {
            public:
                class iterator;
            /* ... */
        };

        template <typename T>
        class vector<T>::iterator
        {
            public:
            /* ... */
                iterator& operator=(const iterator& it);
            /* ... */
        };

        #include "../sources/vector.tpp"
        #include "../sources/iterator.tpp"
    }

    #endif
     


    iterator.tpp
    /* ici, je ne sais pas quoi mettre en type de retour */
    template <typename T>
    vector<T>::iterator& vector<T>::iterator::operator=(const iterator& it)
    {

    }


    Voilà, comme indiqué dans le commentaire, je ne sais pas quoi mettre comme type de retour. Avec un vector<T>::iterator& ou un iterator&, j'obtiens à chaque fois:
    myStl\headers\..\sources\iterator.tpp:41: error: expected constructor, destructor, or type conversion before '&' token
    myStl\headers\..\sources\iterator.tpp:41: error: expected `;' before '&' token
    :: === Build finished: 2 errors, 0 warnings ===


    J'en fais donc, une fois de plus, appel à vous, afin de m'aider à résoudre ce problème (et les autres qui suivront...).

    Comme toujours, merci d'avance ;) .
    • Partager sur Facebook
    • Partager sur Twitter
      5 juillet 2007 à 13:01:06

      Pourquoi tu n'implémentes pas ton itérateur sous forme de simple pointeur ? Pour un vector, ils sont sémantiquement équivalents.
      • Partager sur Facebook
      • Partager sur Twitter
      Anonyme
        5 juillet 2007 à 13:02:38

        Et si j'ai envie de le faire sous forme d'itérateur pour m'entraîner à utiliser les templates ? :p
        • Partager sur Facebook
        • Partager sur Twitter
          5 juillet 2007 à 13:03:19

          Ca veut rien dire, ça:

          template <typename T>
          class vector<T>::iterator
          {
             //[...]
           

          La class iterator du vecteur, tu dois la déclarer _dans_ le vector.
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            5 juillet 2007 à 13:04:55

            J'ai fait une déclaration de la classe iterator dans le vector:

                template <typename T>
                class vector
                {
                    public:
                        class iterator;
                    /* ... */
                };


            Avant que je ne rajoute la fonction qui foire, tout marchait bien, donc je suppose que le reste est _à peu près_ correct.
            • Partager sur Facebook
            • Partager sur Twitter
              5 juillet 2007 à 13:13:13

              Je comprends pas ce que tu souhaites faire :

              class vector<T>::iterator

              ça ne veut rien dire.
              class vector<T> ça veut dire quelque chose, c'est une spécialisation de ta classe template vector lorsque T est égal à un type spécial, par exemple :

              template <char T>
              class vector<T>

              Un itérateur, que ce soit dans la STL, ou dans Boost, ce n'est qu'un simple pointeur. De plus ton opérateur =, c'est pour copier l'intégralité d'un objet, dans l'autre objet. Voilà comment j'implémenterai ça moi, pour rester très simple :

              template <typename T>
              class myVector
              {
                 public:
                    typedef T * iterator;
                    typedef const T * const_iterator;

                    iterator begin () {return mesDonnees;}
                    const_iterator begin () const {return mesDonnees;}
                    iterator end () {return mesDonnees + size;}
                    const_iterator end () const {return mesDonnees + size;}

                    myVector & operator= (const myVector<T> vec)
                    {
                       // Tu vérifies ici que les tailles correspondent

                       iterator itbeg = begin();
                       const_iterator itend = end();
                       const_iterator vecit = vec.begin();

                       for (; itbeg != itend ; itbeg++, vecit++)
                          *itbeg = *vecit;

                       return *this;
                    }

                 private:
                    T * mesDonnees;
                    size_t size;
              };
              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                5 juillet 2007 à 13:21:41

                Ok, donc là j'admets que j'ai pris un mauvais exemple en prenant le vector. Mais prenons, par exemple, l'implémentation de std::list. Ici, les données peuvent être représentées sous forme de liste chaînée (ça dépend de l'implémentation, mais bon), donc un pointeur simple ne suffirait pas pour être un iterator.
                Il faut donc nécessairement que iterator soit une class avec ses opérateurs (par exemple, l'operator++ irait chercher le membre next de la structure qui représente les données pour accéder au prochain élément).
                Si j'essaie de faire cela, je me retrouverai confronté au même problème.

                Ou alors je n'ai strictement rien compris à la notion d'itérateur dans le cas de structures plus complexes qu'un tableau telles qu'une liste chaînée, et alors je vous demande de m'expliquer comment implémenter un itérateur sur une liste chaînée (en gros, hein ^^ ).

                EDIT: ok, après avoir jeté un coup d'oeil à l'implémentation de la STL, j'ai compris comment cela marchait: les itérateurs sont bien des classes, mais ils sont définis à l'extérieur du conteneur, et ces conteneurs ne font ensuite qu'un typedef sur ces itérateurs. Merci à toutes vos réponses ;) . Pour le moment, je n'ai pas d'autres questions, mais ça viendra sûrement bientôt...
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  5 juillet 2007 à 14:03:33

                  Je me demandais une chose qui n'a pas un rapport direct avec l'implémentation du vector mais qui peut m'être utile par la suite: existe-t-il un type équivalent à size_t, mais qui soit signé ?

                  Merci bien :) .
                  • Partager sur Facebook
                  • Partager sur Twitter
                    5 juillet 2007 à 14:26:14

                    Le type int, tout simplement.
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      5 juillet 2007 à 14:35:35

                      Mais le type int risque de ne pas suffire dans le pire des cas.
                      Il me semble avoir lu quelque part que le type size_t suffisait pour contenir n'importe quelle taille qui peut être contenue en mémoire, ce que ne fait pas forcément int...

                      EDIT: après quelques recherches, j'ai finalement trouvé le type ptrdiff_t qui semble correspondre au type size_t, mais en signé :) .

                      EDIT² : voilà, je vais à présent vous montrer mon code, afin que vous me disiez ce qui pose problème ou pas. Le code semble fonctionnel, mais je ne suis pas sûr qu'il soit à toute épreuve et tout et tout, enfin bref...

                      Après vos remarques, j'ai modifié quelque peu mon organisation: tout le code est réuni dans le fichier .h, tant pis pour la modularité, ça me compliquait trop la vie :-° .
                      Les itérateurs ne sont effectivement que des pointeurs, mais grâce au typedef, si l'envie me prend de les remplacer par une classe, ce sera très simple à faire.
                      Comme cela était présent dans la STL, j'ai également rajouté un typedef sur size_t en size_type, comme ça, à nouveau si l'envie m'en prend, il sera très facile de changer ce type en un autre.
                      J'ai également, comme dans la STL, fait un typedef sur ptrdiff_t, même si je ne m'en sers pas :p .
                      Les seules choses que je n'ai pas implémentées sont les reverse_iterator et les opérateurs de comparaison, mais bon :-°

                      Trêve de bavardages, voici mon code, bon courage...

                      vector.h
                      #ifndef DEF_VECTOR
                      #define DEF_VECTOR

                      namespace myStl
                      {
                          template <typename T>
                          class vector
                          {
                              public:
                                  typedef T value_type;
                                  typedef value_type* pointer;
                                  typedef value_type* iterator;
                                  typedef const value_type* const_iterator;
                                  typedef value_type& reference;
                                  typedef const value_type& const_reference;
                                  typedef size_t size_type;
                                  typedef ptrdiff_t difference_type;

                                  vector()
                                  {
                                      taille = 0;
                                      max_taille = 1;
                                      tab = new value_type[1];
                                  }

                                  vector(const vector& v)
                                  {
                                      taille = v.taille;
                                      max_taille = v.max_taille;
                                      tab = new value_type[max_taille];

                                      for(size_type i=0 ; i<taille ; i++)
                                          tab[i] = v.tab[i];
                                  }

                                  vector(size_type n, const value_type& t = value_type())
                                  {
                                      taille = n;

                                      for(max_taille=1 ; max_taille<=n ; max_taille<<=1);
                                      tab = new value_type[max_taille];

                                      for(size_type i=0 ; i<taille ; i++)
                                          tab[i] = t;
                                  }

                                  ~vector()
                                  {
                                      delete[] tab;
                                  }

                                  vector& operator=(const vector& v)
                                  {
                                      vector<value_type> tmp(v);
                                      swap(tmp);
                                  }

                                  void swap(vector& v)
                                  {
                                      value_type* tab_v = v.tab;
                                      size_type taille_v = v.taille;
                                      size_type max_taille_v = v.max_taille;

                                      v.tab = tab;
                                      v.taille = taille;
                                      v.max_taille = max_taille;

                                      tab = tab_v;
                                      taille = taille_v;
                                      max_taille = max_taille_v;
                                  }

                                  bool empty() const
                                  {
                                      return size()==0;
                                  }

                                  size_type size() const
                                  {
                                      return taille;
                                  }

                                  size_type max_size() const
                                  {
                                      return max_taille;
                                  }

                                  size_type capacity() const
                                  {
                                      return max_size();
                                  }

                                  void reserve(size_type t)
                                  {
                                      for(;max_taille <= t; max_taille <<=1);

                                      value_type* tmp_tab = tab;

                                      tab = new value_type[max_taille];
                                      for(size_type i=0 ; i<size() ; i++)
                                          tab[i] = tmp_tab[i];

                                      delete[] tmp_tab;
                                  }

                                  reference operator[](size_type idx)
                                  {
                                      assert(idx <= size());
                                      return tab[idx];
                                  }

                                  const_reference operator[](size_type idx) const
                                  {
                                      assert(idx <= size());
                                      return tab[idx];
                                  }

                                  reference back()
                                  {
                                      reference ref = (*this)[size()-1];
                                      return ref;
                                  }

                                  const_reference back() const
                                  {
                                      const_reference ref = (*this)[size()-1];
                                      return ref;
                                  }

                                  reference front()
                                  {
                                      reference ref = (*this)[0];
                                      return ref;
                                  }

                                  const_reference front() const
                                  {
                                      const_reference ref = (*this)[0];
                                      return ref;
                                  }

                                  iterator begin()
                                  {
                                      iterator it = &(*this)[0];
                                      return it;
                                  }

                                  const_iterator begin() const
                                  {
                                      const_iterator it = &(*this)[0];
                                      return it;
                                  }

                                  iterator end()
                                  {
                                      iterator it = &(*this)[size()];
                                      return it;
                                  }

                                  const_iterator end() const
                                  {
                                      const_iterator it = &(*this)[size()];
                                      return it;
                                  }

                                  iterator insert(iterator pos, const T& x)
                                  {
                                      assert(pos >= tab && pos <= (tab+size()));

                                      size_type idx = pos - tab;
                                      taille++;
                                      reserve(size());

                                      value_type* tab_tmp = tab;
                                      tab = new value_type[max_taille];

                                      for(size_type i=0 ; i<idx;i++)
                                          tab[i] = tab_tmp[i];
                                      tab[idx] = x;
                                      for(size_type i=idx+1 ; i<size() ;i++)
                                          tab[i] = tab_tmp[i-1];

                                      delete[] tab_tmp;
                                      return &(*this)[idx];
                                  }

                                  iterator insert(iterator pos, size_type n, const T& x)
                                  {
                                      iterator it = pos;
                                      for(size_type i=0 ; i<n ; i++)
                                          it = insert(it, x);
                                      return it;
                                  }

                                  void push_back(const T& x)
                                  {
                                      insert(end(), x);
                                  }

                                  iterator erase(iterator pos)
                                  {
                                      assert(pos >= tab && pos <= tab+size());

                                      if(pos == tab+size())
                                          pos = tab+size()-1;

                                      size_type idx = pos-tab;

                                      taille--;
                                      for(size_type i=idx;i<size();i++)
                                          (*this)[i] = (*this)[i+1];
                                      return &(*this)[idx];
                                  }

                                  iterator erase(iterator first, iterator last)
                                  {
                                      if((size_t)last < (size_t)first)
                                      {
                                          iterator tmp = last;
                                          last = first;
                                          first = tmp;
                                      }
                                      iterator it = first;
                                      for(size_type i=0 ; i<(unsigned)(last-first) ; i++)
                                          it = erase(first);
                                      return it;
                                  }

                                  void pop_back()
                                  {
                                      erase(end()-1);
                                  }

                                  void clear()
                                  {
                                      erase(begin(), end());
                                  }

                                  void resize(size_type n, const T& x = T())
                                  {
                                      if(n < size())
                                          erase(begin() + n, end());
                                      else
                                          insert(end(), n - size(), x);
                                  }

                              private:
                                  value_type* tab;
                                  size_type taille;
                                  size_type max_taille;
                          };
                      }

                      #endif
                       


                      Pour le tester, prenez n'importe quel code utilisant des std::vector, incluez le code ci-dessus et remplacez juste le namespace std par myStl.

                      Merci à ceux qui auront la patience de lire ce code et de m'aider à progresser (première fois que je réalise une classe template :D ).

                      Si tout va bien, la prochaine étape sera la std::list...
                      • Partager sur Facebook
                      • Partager sur Twitter
                        5 juillet 2007 à 21:20:59

                        Outre le fait que je pense qu'il soit parfaitement inutile de refaire ces classes, même pour un but d'entraînement (si tu veux d'entraîner avec les templates, regarde du côté des expression templates, c'est vachement intéressant à coder :)).

                        Une remarque quand même :

                        vector(size_type n, const value_type& t = value_type())
                                    {
                                        taille = n;

                                        for(max_taille=1 ; max_taille<=n ; max_taille<<=1);
                                        tab = new value_type[max_taille];

                                        for(size_type i=0 ; i<taille ; i++)
                                            tab[i] = t;
                                    }


                        Comprend pas. Si je comprends bien tu veux créer un tableau de n éléments initialisés à la valeur t. Pourquoi ne pas faire tab = new value_type [n] tout simplement ? Plutôt qu'une boucle ?

                        Sinon le reste je n'ai pas lu, mais ça a l'air plutôt bien.
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          5 juillet 2007 à 21:31:20

                          Il ya encore mieux pour s'entrainer.
                          La méta-progrmmation.
                          Tu as un tuto la dessue sur www.developpez.com
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            5 juillet 2007 à 21:39:43

                            La boucle, c'est afin d'avoir toujours une capacité/taille maximale multiple de 2, j'avais lu je ne sais plus où que pour optimiser les réallocations en série, il vaut mieux multiplier la taille totale par 2 à chaque fois que simplement rajouter 1 élément à chaque fois.
                            De plus, il paraît que l'ordinateur travaille avec des puissances de 2, donc je lui facilite la tâche ^^ .

                            Si je recode des trucs existants, c'est simplement parce que j'ai peu d'imagination/courage/temps :D .
                            Quant aux expressions templates, voir juste en-dessous...

                            @david : je l'ai lu ce tuto, mais j'ai l'impression que c'est encore un peu trop compliqué pour moi :euh: donc je m'entraîne avec des trucs plus simples.
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Anonyme
                              5 juillet 2007 à 22:08:29

                              le tuto est complique sur la partie maths a la fin.
                              Mais avant c'est tres comphrensible est et on faire des choses bien avec.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                5 juillet 2007 à 22:55:29

                                La métaprog c'est pas extrêmement compliqué dans le principe, suffit juste de piger le coup. Tout est basé sur le fait que tout doit être calculé à la compilation et non à l'execution. T'auras plus de détails sur le tuto de developpez.com sur ça, qui traite aussi des expressions templates, mais voilà un petit exemple. Imagine que tu souhaites calculer un nombre élevé à une quelconque puissance. Soit tu fais appel à la fonction standard pow, ou soit tu t'amuses un peu avec la méta prog. Par exemple, ce petit programme, très simple :

                                template <int N, int EXP>
                                class Pow
                                {
                                   enum {result = N * Pow <N, EXP-1>::result;}
                                };

                                // Spécialisation lorsque EXP = 0
                                template <int N>
                                class Pow <N, 0>
                                {
                                   enum {result = 1;}
                                };


                                Outre le fait que ça fasse vachement classe :-°, ça permet de pas mal améliorer les performances.
                                En fait, le enum, si tu préfères pour rester simple, tu peux considérer ça comme un static int const result (avec une petite différence quand même, mais c'est pas important, c'est juste pour le principe).
                                Ainsi, si tu cherches le résultat de 4 élevé à la puissance 5, tu feras ça dans ton code :

                                int monResultat = Pow<4, 8>::result;

                                Le compilateur va, à l'instanciation, instancié la classe suivante :
                                Pow <4, 7>, ou result = 4 * Pow <4, 6>::result. Or là le compilo ne connaissant pas Pow <4, 6>::result, va, à la compilation, instancié Pow <4, 7>, et ainsi de suite, jusqu'à ce que EXP soit égal à 0, là le compilateur instanciera la classe spécialisée.

                                En gros, tu peux voir ça comme une fonction récursive, sauf que, à la fin de la compilation, dans la tête du compilo, tu auras Pow<4, 7>::result = 16384, et donc aucun coup de calcul si tu as toutes les optimisations du compilo d'activées, et hop :p.

                                Sinon, je te conseille aussi le bouquin C++ Templates : The Complete Guide, qui est vraiment excellent ;).
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  5 juillet 2007 à 23:36:40

                                  J'ai beau être un partisant de "le C pas au début", par contre, je place la gestion de la mémoire avant la méta-prog -- à la limite, on peut voir lisp et prolog (qui ont des petits points communs avec la méta-prog) avant la gestion de la mémoire.

                                  Allez-y tranquillement. Une classe matrice, c'est un excellent exo. Et avant d'arriver à l'élimination des temporaires par expressions templates et autres hacks avancés, il y a déjà bien assez à faire.
                                  Ne serait que les traits, la reconnaissance des types reference/value_type qui font bien pour optimiser les passages de paramètres (déjà un chouilla avancé), le couplage à une classe vecteur (auto_vector) qui supporte la sémantique de déplacement, ...

                                  Pour l'organisation du code, avec les templates, j'ai laissé tomber : tout dans le fichier, à la Java.


                                  Les itérateurs ne sont pas des pointeurs !!! C'est le contraire.
                                  Au choix, l'approche GCC/GNU avec des itérateurs "libres" reliés avec des typedefs. Ou alors une classe "nested".


                                  Pour le code, remarques supplémentaires:

                                  * la copie. Tant qu'à faire, profite des algos standard comme std::copy

                                  * Pareil avec swap() : utilises std::swap sur les membres de ta structure

                                  * Aurjourd'hui, "<<=1" est limite de l'obfuscation. Les compilos savent optimiser et reconnaitre que c'est la même chose que "*=2"

                                  * reserve() peut recevoir une taille <= à la capacité courante

                                  * Ta précondition sur l'opérateur[] n'est pas bonne. :s/<=/</
                                  D'ailleurs, tu pourrais aussi en utiliser une sur back() et front()

                                  * Ton écriture de end devrait planter (tu esquives grâces à la mauvaise précondition).
                                  -> iterator res(m_tab+size());
                                  serait plus juste

                                  De plus, si je ne m'abuse, certains outils pourraient détecter un accès hors mémoire allouée avec un "&p[T]", alors que "p+T" ne déclenche pas d'accès hors bornes.

                                  * Dans insert, il y a une optimisation possible : si tu augmentes la capacité, inutile de copier deux fois : une première pour le redimensionnement, et une seconde pour déplacer les éléments de queue.
                                  De nouveau, il y a des algos de déplacement dans <algorithm>

                                  (je n'ai pas regardé le reste)
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                  Anonyme
                                    6 juillet 2007 à 8:12:06

                                    Citation : lmghs

                                    * la copie. Tant qu'à faire, profite des algos standard comme std::copy


                                    Comme toujours, je voulais utiliser le moins possible d'autres bibliothèques :-° . En restant comme ça, je n'utilise aucune autre bibliothèque. En plus, je compte, tant qu'à faire, même si certains jugeront ça inutile, réimplenter les algos de base.

                                    Citation : lmghs

                                    * Pareil avec swap() : utilises std::swap sur les membres de ta structure


                                    Peu avant que tu écrives ce message, j'ai justement réimplenté std::swap :
                                    template <typename T>
                                    void swap(T& a, T& b)
                                    {
                                        T tmp(b);
                                        b = a;
                                        a = tmp;
                                    }

                                    Citation : lmghs

                                    * Aurjourd'hui, "<<=1" est limite de l'obfuscation. Les compilos savent optimiser et reconnaitre que c'est la même chose que "*=2"

                                    Je m'en doute, mais ça faisait classe ^^ .

                                    Citation : lmghs

                                    * reserve() peut recevoir une taille <= à la capacité courante

                                    Effectivement, petit oubli :euh: .

                                    Citation : lmghs

                                    * Ta précondition sur l'opérateur[] n'est pas bonne. :s/<=/</

                                    Ca je m'en doutais malheureusement, mais sinon ça posait problème pour d'autres méthodes qui font appel à cet opérateur, et comme je me suis débrouillé pour avoir toujours au moins une case de plus :-° . Mais si ça pose vraiment problème, je vais corriger ça de ce pas, ça me fera juste un peu moins de généricité pour d'autres méthodes.

                                    Citation : lmghs

                                    D'ailleurs, tu pourrais aussi en utiliser une sur back() et front()

                                    Quelle condition ? Vérifier qu'il y au moins un élément ? C'est possible :) .

                                    Citation : lmghs

                                    * Ton écriture de end devrait planter (tu esquives grâces à la mauvaise précondition).
                                    -> iterator res(m_tab+size());
                                    serait plus juste

                                    De plus, si je ne m'abuse, certains outils pourraient détecter un accès hors mémoire allouée avec un "&p[T]", alors que "p+T" ne déclenche pas d'accès hors bornes.

                                    Ok, je vais régler ça, je n'y avais malheureusement pas pensé :honte: .

                                    Citation : lmghs

                                    * Dans insert, il y a une optimisation possible : si tu augmentes la capacité, inutile de copier deux fois : une première pour le redimensionnement, et une seconde pour déplacer les éléments de queue.
                                    De nouveau, il y a des algos de déplacement dans <algorithm>


                                    Tiens oui, là aussi je n'y avais pas pensé, merci :) . Et je viens de voir que pour le 2e insert (insertions entre 2 bornes), j'aurai aussi des problèmes de réallocations multiples et donc trop nombreuses... En fait, je crois que je vais le recoder sans utiliser le premier insert.

                                    Tu as aussi parlé des classes de traits, je comptais également m'entraîner à l'utilisation des classes, non pas de traits, mais de politique ainsi qu'à l'algorithmique. Pour ça, une fonction membre sort fera l'affaire, avec différentes structures pour implémenter les différents tris.


                                    Une fois de plus, merci beaucoup, surtout que tu es l'un des seuls à avoir le courage de me lire à chaque fois (et je comprends tout à fait les autres :D ).



                                    @bakura10 : pour pow et les autres boucles, je comprenais, juste de la récursivité, c'est aux expressions templates que je commence à galérer (j'ai relu ça plusieurs fois hier sans réussir à comprendre :( ). En plus, pour les boucles, j'ai dû mal à comprendre l'utilité, vu que tout est connu à la compilation; en général, quand j'ai ça, je prends ma calculatrice et voilà, c'est plus rapide à la compilation comme ça.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Anonyme
                                      6 juillet 2007 à 10:27:27

                                      bakura10 >> c'est bon mais non.
                                      class met les attribut par default en private.
                                      Donc soit tu met un publique explicite soit tu met strcut au lieu de class.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        6 juillet 2007 à 11:44:35

                                        Davidbrcz > En effet petit oubli de ma part :p. Au début je voulais mettre struct et à la fin je me suis dit bon je vais mettre class finalement, et j'ai oublié d'ajouter le public :/.

                                        Cyprien_ > Les expressions templates ça te permet notamment de supprimer les temporaires dans des expressions telles que a = b + c. C'est vrai qu'au début la syntaxe paraît vraiment étrange, mais c'est un coup à prendre.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          6 juillet 2007 à 23:28:37

                                          Politiques et traits se ressemblent, et les deux peuvent avoir un intérêt ici.

                                          Autrement, tout cela me fait penser à deux choses:
                                          - les notes sur la programmation d'Alex Stephanov (un des créateurs de la STL) -- le lien se retrouve depuis le wiki d'ASL -> (ah ah! voilà la release de Juillet) http://opensource.adobe.com/wiki/index.php/Coding_Guidelines

                                          - flex_string d'Andrei Alexandrescu (http://erdani.org/ , section code)
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                          Anonyme
                                            7 juillet 2007 à 9:36:07

                                            Pour les expressions templates, je relirai ça une autre fois, car hier j'ai relu plusieurs fois la partie du tuto concernant la "simplification" d'expressions matématiques, et je n'ai toujours rien compris :euh: .

                                            A présent, si je poste, c'est surtout parce que j'ai un problème pour implémenter mon tri... J'ai commencé simplement avec le tri à bulles, et parce qu'il risquait d'y avoir beaucoup de tris au final, j'ai séparé les alogrithmes dans un autre fichier. Voilà ce que ça donne:

                                            vector.h
                                            /* ... */
                                            #include "tab_sort.h"

                                            namespace myStl
                                            {
                                                template <typename T>
                                                class vector
                                                {
                                                    public:
                                                        /* ... */
                                                        template <typename Tri>
                                                        void sort()
                                                        {
                                                            Tri<T>::sort(tab, taille);
                                                        }
                                                        /* ... */
                                                };

                                                /* ... */
                                            }


                                            tab_sort.h
                                            #ifndef DEF_TAB_SORT
                                            #define DEF_TAB_SORT

                                            #include "vector.h"
                                            /* utilities.h contient la fonction swap */
                                            #include "utilities.h"

                                            namespace myStl
                                            {
                                                template <typename T>
                                                struct bubbleSort
                                                {
                                                    static void sort(T* v, size_t size)
                                                    {
                                                        for(size_t i=1 ; i<size ; i++)
                                                        {
                                                            for(size_t j=0 ; j<size-i ;j++)
                                                            {
                                                                if(v[j] > v[j+1])
                                                                    myStl::swap(v[j], v[j+1]);
                                                            }
                                                        }
                                                    }
                                                };
                                            }

                                            #endif
                                             


                                            Enfin, l'appel dans le main:
                                                vector<int> v;
                                                for(int i=10 ; i ; i--)
                                                    v.push_back(i);
                                                v.sort<bubbleSort>();


                                            J'ai fait l'appel comme je le pensais (en suivant quand même le modèle de la FAQ de developpez :-° ) et j'obtiens une belle erreur...
                                            myStl\headers\vector.h:246: error: `Tri' is not a template
                                            myStl\headers\vector.h:246: error: declaration of `sort' not in a namespace surrounding `::'
                                            myStl\headers\vector.h:246: error: `sort' should have been declared inside `::'
                                            myStl\headers\vector.h:246: warning: declaration of 'sort' shadows a member of 'this'
                                            myStl\main.cpp:19: error: no matching function for call to `myStl::vector<int>::sort()'
                                            :: === Build finished: 4 errors, 1 warnings ===


                                            Au risque de m'en lasser, je vous remercie encore une fois de votre aide :) .
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              7 juillet 2007 à 17:26:14

                                              Je suis justement en train d'écrire un tuto sur Traits et Policies... Je tiens au courant ;)
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Anonyme
                                                8 juillet 2007 à 18:25:15

                                                Petit up, je ne compte pas attendre ton tuto pour finir ^^ .

                                                EDIT: oups, je viens de voir ton tuto sur developpez. Je le lis puis je réédite.
                                                EDIT²: re-oups, je viens de voir qu'il n'était pas complet :lol: .
                                                EDIT3: c'est bon, grâce à Alp ;) . Il suffisait de templater la fonction de tri à la place de la structure.
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  8 juillet 2007 à 21:44:41

                                                  En effet il n'est pas complet, je suis en train, j'ai dit :)
                                                  Et oui c'est résolu cf forum de developpez(tu peux donner l'url si tu veux, pour aider ceux qui liront ton sujet à comprendre).
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  Anonyme
                                                    9 juillet 2007 à 8:19:21

                                                    Ok, donc pour ceux qui veulent aller voir, c'est ici.

                                                    Bref, merci à tous ceux qui m'ont aidé, je crois que j'ai fini à présent.
                                                    A une prochaine :D .
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      9 juillet 2007 à 10:45:19

                                                      C'est quand tu veux :-"
                                                      Ps : j'avance petit à petit le tuto sur traits/policies.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter

                                                      Classe std::vector

                                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                      • Editeur
                                                      • Markdown