IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

vector<Mere> et vector<Fille> même combat


Sujet :

C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut vector<Mere> et vector<Fille> même combat
    Bonjour,

    Dans mon programme, j'utilise des std::vector de classes qui héritent toutes d'une même classe mère comme suit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class Symbol {...};
    class Polygon : public Symbol {...};
    class Line : public Symbol{...};
    j'ai ailleurs dans le programme 2 vecteurs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::vector<Line> _vectLine;
    std::vector<Polygon> _vectPolygon;
    je souhaite écrire une méthode qui s'appelle aussi-bien sur un vector<Line> que sur un vector<Polygon>, donc j'écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void doSomething(std::vector<Symbol> vect);
    seulement voilà, lors de l'appel de ma méthode, il me dit qu'il ne peut pas convertir les vecteurs ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::vector<Line> _vect;
    doSomething(_vect);
    error C2440: 'cast de type'*: impossible de convertir de 'std::vector<_Ty>' en 'std::vector<_Ty>'
    Je suis sûr que la chose doit être possible mais la syntaxe m'échappe.
    J'ai pas envie de devoir déclarer tout mes vecteurs de classe fille comme des vecteurs de classe mère ...

    d'avance je vous remercie de votre aide

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    C'est normal...

    Il y a deux raisons à cela:
    • D'abord, vectro<Type1> représente un type différent de vector<Type2>
    • Ensuite, pour pouvoir profiter du polymorphisme, il faut impérativement manipuler des références ou des pointeurs.

    (au passage, tu devrais transmettre ton vecteur par référence, éventuellement constante si la fonction ne dois pas modifier le vecteur, mais cela t'éviterait des copies inutiles et certainement très gourmandes en ressources

    Par contre, si tu avais un vecteur de pointeurs sur Symbol, tu pourrait faire cohabiter des lignes et des polygones, avec la restriction que tu n'aurais accès qu'aux fonctions membres déclarées pour le type Symbol...

    Si tel n'est pas ton souhait, Un petit coup de template devrait te venir en aide

    Quelque chose proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template<class T>
    void doSomething(std::vector<T> vect);
    (non testé, il manque peut être un typename quelque part ) devrait pouvoir faire l'affaire
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Même réponse que koala01, les template vont te permettre de le faire.

    Pour aller plus loin dans les template, et pour être encore un peut plus dans l'"esprit STL", on pourrai faire ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template<iterator T>
    void doSomething(iterator iter, iterator end)
    {
      for(/**/; iter != end; ++iter)
        doSomething(*iter);
    }
    Comme ca, même si c'est pas un vector, ca marche quand même.

    Et sinon, si t'as pas envie de faire des template, et que tu est SUR que tu utilise un vector, un boost::array, ou un tableau, tu peut faire comme ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void doSomething(Symbol *iter, Symbol *end)
    {
      for(/**/; iter != end; ++iter)
        doSomething(*iter);
    }
    EDIT: Je viens de tilter que la deuxième solution ne marchera pas car quand on fera ++iter le pointeur avancera de sizeof(Symbol) octet, ce qui peut être faux.
    En fait il fraudai être sur un tableau de pointeur et passer a doSomething des pointeurs de pointeurs mais ca commence a être un peut alambiqué.

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    A titre tout à fait personnel, je n'aime pas trop les boucle pour amputée d'une de leur valeur...

    Pour suivre ton inspiration, je ferais donc plutôt un truc proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<class T>
    void doSomething(T it, T end)
    {
        while(it!=end)
        {
            (*it).laFonctionVoulue();
            ++it;
        }
    }
    voire, pour pouvoir utiliser les fonctions utilisant des écarts (for_each et autres), de créer un foncteur prenant la forme de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<class T>
    struct doSomething
    {
     
        void operator()(T /* const */ & value) /* const*/
        {
            value.laFonctionAAppeler();
        }
    };
    Il est d'ailleurs à noter que, l'idéal est (aussi) de ne jamais exposer un conteneur si tu peux faire sans et d'essayer autant que possible de n'exposer que les itérateurs de débuts et de fin sur ce conteneur.

    En effet, le jour où tu souhaitera passer d'un std::vector à un std::list ou meme à un std::map(par exemple), la solution qui passe par un foncteur restera tout à fait valide, et même la boucle for_each (ou de toute autre fonction manipulant des écarts) ne devra pas être modifiée.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre très actif Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Par défaut
    Quand il s'agit juste d'appeler un membre sur chaque élément d'un container, je préfère utiliser directement std::mem_fun plutôt que de (re)créer un foncteur pour ça.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::for_each(v.begin(), v.end(), std::mem_fun(&Symbol::virtual_fun));
    Par rapport à Nogane
    EDIT: Je viens de tilter que la deuxième solution ne marchera pas car quand on fera ++iter le pointeur avancera de sizeof(Symbol) octet, ce qui peut être faux.
    En fait il fraudai être sur un tableau de pointeur et passer a doSomething des pointeurs de pointeurs mais ca commence a être un peut alambiqué.
    En fait, si ça va fonctionner. koala01 a une solution plus générique.
    Par contre, il faudra passer par std::iterator_traits<T> si on veut connaître le type déréférencer ou la distance entre les élems.

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par metagoto Voir le message
    Par rapport à Nogane
    En fait, si ça va fonctionner. koala01 a une solution plus générique.
    Par contre, il faudra passer par std::iterator_traits<T> si on veut connaître le type déréférencer ou la distance entre les élems.
    Effectivement, la fonction pourrait se présenter sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<class T, class iter=std::iterator_traits<T> >
    void foo(iter it, iter end)
    {
        while(it!=end)
        {
            (*it).laFonctionQuiVaBien();
            ++it;
        }
    }
    mais, le jour où tu voudrais faire en sorte qu'elle fonctionne avec une std::map (ou autre container associatif utilisant des tuple), il faudra créer une fonction dont le nom diffère et qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<class K, class V, class iter=std::iterator_traits<typename std::pair<K const,V> > >
    void bar(iter it, iter end)
    {
        while(it!=end)
        {
            /*acces éventuel à la clé */
            std::cout<<(*it).first;
     
            (*it).second.laFonctionQuiVaBien();
            ++it;
        }
    }
    L'un dans l'autre, la solution passant par un foncteur me semble bien plus pertinente et ce, d'autant plus que, comme je l'ai fait remarquer:
    1. il est préférable d'utiliser les fonctions qui manipulent des écart [debut,fin) plutôt que des boucle
    2. il est préférable d'éviter d'exposer ce qui n'a pas besoin de l'être (si on peut éviter d'exposer toute fonction propre au container qui représente le membre d'une classe, c'est toujours ça de gagné )
    3. le principe de la délégation des taches semble indiquer que ce serait à l'objet contenu de travailler lorsque l'on parcoure le conteneur.

    Au sujet du troisième point, il serait d'ailleurs possible d'avoir un foncteur imbriqué, éventuellement déclaré ami de l'objet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    class Base
    {
            friend class FoncteurBase;
        public:
            virtual ~Base(){}
            struct FoncteurBase
            {
                void operator()(Base /*const*/ & b) /*const*/
                {
                    std::cout<<"Base"<<std::endl;
                }
            };
    };
    class Derivee : public Base
    {
     
            friend class FoncteurDerivee;
        public:
            virtual ~Derivee(){}
            struct FoncteurDerivee
            {
                void operator()(Derivee /*const*/ & d) /*const*/
                {
                    std::cout<<"derivee"<<std::endl;
                }
            };
    };
    int main()
    {
        std::vector<Base> tabBase;
        for(int i=0;i<10;++i)
            tabBase.push_back(Base());
        std::vector<Derivee> tabDerivee;
        for(int i=0;i<10;++i)
            tabDerivee.push_back(Derivee());
        for_each(tabBase.begin(),tabBase.end(),Base::FoncteurBase());
        /* polymorphisme inside ? */
        for_each(tabDerivee.begin(),tabDerivee.end(),Base::FoncteurBase());
        /* pas de polymor ici */
        for_each(tabDerivee.begin(),tabDerivee.end(),Derivee::FoncteurDerivee());
        return 0;
    }
    Évidemment, tu perds l'avantage des template si le comportement reste identique, mais tu gagne le polymorphisme éventuel...

    Et je ne parle même pas de la possibilité de créer un foncteur imbriqué template

    Enfin, bref, comme tu peux le remarquer, les foncteurs te permettent à mon sens clairement une plus grande souplesse...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre très actif Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Effectivement, la fonction pourrait se présenter sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<class T, class iter=std::iterator_traits<T> >
    void foo(iter it, iter end)
    {
        while(it!=end)
        {
            (*it).laFonctionQuiVaBien();
            ++it;
        }
    }
    En fait il n'y a pas besoins de déclarer un paramètre T puis un paramètre Iter ensuite avec une default value. Directement template<typename Iter> suffit.
    Aussi, normalement les functions template n'acceptent pas de paramètres templates par défaut.

    mais, le jour où tu voudrais faire en sorte qu'elle fonctionne avec une std::map (ou autre container associatif utilisant des tuple), il faudra créer une fonction dont le nom diffère et qui serait proche de
    C'est intéressant parce que j'ai pas souvenir d'avoir vu un "type traits" tout fait pour pouvoir opérer cette distinction entre les différentes manières d'accéder au type déréférencé via un itérateur pour les containers standards. (j'ai regardé boost type traits, mais rien). Du coup j'ai testé un truc, que voilà:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    // lib part
    struct true_ { };
    struct false_ { };
     
    template<typename T>
    struct is_pair
    {
      typedef false_ type;
    };
     
    template<typename K, typename V>
    struct is_pair<std::pair<K,V> >
    {
      typedef true_ type;
    };
     
     
    // specialisée pour type assoc
    template <class Iter>
    void doSomethingImpl(Iter first, Iter last, const true_&) {
      // deref avec it->second
    }
     
    // specialisée pour type normal
    template <class Iter>
    void doSomethingImpl(Iter first, Iter last, const false_&) {
      // deref avec *it
    }
     
    // interface
    template <class Iter>
    void doSomething(Iter first, Iter last) {
      typedef typename std::iterator_traits<Iter>::value_type value_type;
      doSomethingImpl(first, last, typename is_pair<value_type>::type());
    }
     
    doSomething(map.begin(), map.end());
    doSomething(vec.begin(), vec.end());
    [*]il est préférable d'utiliser les fonctions qui manipulent des écart [debut,fin) plutôt que des boucle
    Ca revient plus ou moins au même. Cependant, quand on est certain de boucler sur tous les éléments sur tout un range, j'ai plus l'habitude d'utiliser un for qu'un while. Je ne sais pas pourquoi, une question de feeling sûrement

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2006
    Messages
    126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2006
    Messages : 126
    Par défaut
    waouw merci pour toutes ces réponses

    je vais prendre le temps de bien tout lire et d'apprendre toutes ces choses qui me sont encore inconnues

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par metagoto Voir le message
    Aussi, normalement les functions template n'acceptent pas de paramètres templates par défaut.
    Les fonctions template ne supportent pas la spécialisation partielle... Pas les paramètres template par défaut
    Ca revient plus ou moins au même.
    Ca revient au même du fait que tu crée une fonction qui travaille sur un écart...

    Mais c'est à mettre en relation avec la deuxième restriction dont je parle qui consiste à n'exposer que ce qui doit être fait
    Cependant, quand on est certain de boucler sur tous les éléments sur tout un range, j'ai plus l'habitude d'utiliser un for qu'un while.
    Ce que je n'aime pas, ce n'est pas d'utiliser une boucle pour pour parcourir tout un écart, ce que je n'aime pas, c'est d'amputer la boucle pour d'une de ses instructions...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(it=truc.begin();it!=truc.end();++it)
    ne me dérange absolument pas

    Par contre,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for( ; truc!=bidule ; ++truc)
    etc me choquent au plus haut point
    Je ne sais pas pourquoi, une question de feeling sûrement
    Oui, très clairement
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Sisi les paramètre templates par défaut sur les fonctions ça _existe_ pas. (une erreur du à l'historique il me semble.)
    Après sûrement que certains compilo l'introduise. Je sais que y'a pas de difficultés particulière qui l'empêche.

  11. #11
    Membre très actif Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Les fonctions template ne supportent pas la spécialisation partielle... Pas les paramètres template par défaut
    Si si (non non). J'ai vérifié, dans le doute:
    http://www.open-std.org/jtc1/sc22/wg...fects.html#226
    Pas de défauts arguments pour les functions template, mais ça va changer pour le prochain standard.
    (mon gcc me reportait une erreur de toute façon sans un -std=c++0x)

    Ce que je n'aime pas, ce n'est pas d'utiliser une boucle pour pour parcourir tout un écart, ce que je n'aime pas, c'est d'amputer la boucle pour d'une de ses instructions...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(it=truc.begin();it!=truc.end();++it)
    ne me dérange absolument pas

    Par contre,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for( ; truc!=bidule ; ++truc)
    etc me choquent au plus haut point
    Bizarre, moi ça ne me choque pas
    C'est clair que je préfère éviter de "coder" une boucle à la main quand un algo standard est déjà dispo.
    Pour les for loops "amputées" comme tu dis, ça montre souvent clairement une variation importante, du genre l'initialiseur qui doit persister au delà du scope du bloc, ou une condition d'arrêt non triviale. Bref, ça documente autant que ça fait "moche"

    Edit: grillé par Goten

  12. #12
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par metagoto Voir le message
    Si si (non non). J'ai vérifié, dans le doute:
    http://www.open-std.org/jtc1/sc22/wg...fects.html#226
    Pas de défauts arguments pour les functions template, mais ça va changer pour le prochain standard.
    (mon gcc me reportait une erreur de toute façon sans un -std=c++0x)
    Effectivement, j'avais oublié avoir spécifié que j'utilisais la nouvelle norme pour mon projet de test

    Voilà bien la preuve qu'il faut tout vérifier avant de faire des déclarations intempestives

    Ceci dit, le fait que la nouvelle norme les accepte est, pour moi, une bonne chose
    C'est clair que je préfère éviter de "coder" une boucle à la main quand un algo standard est déjà dispo.
    Là dessus, nous sommes bien d'accord
    Pour les for loops "amputées" comme tu dis, ça montre souvent clairement une variation importante, du genre l'initialiseur qui doit persister au delà du scope du bloc, ou une condition d'arrêt non triviale.
    Justement, j'associe le compteur (ou l'itérateur) d'une boucle pour à quelque chose qui peut, s'il doit subsister en dehors du scope de la boucle, exister dans un état indéfini avant, mais dont la définition fait partie intégrante de la boucle elle-même.

    Autrement dit, je n'ai rien contre un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int i; /* on utilisera i après la boucle, mais il n'est pas nécessaire
            * de le définir avant
            */
    for( i = 0;i<MAXITER;++i)
    {
        if(condition_de_sortie)
            break;
    }
    if(i!=MAXITER)
    {
        /* ...*/
    }
    ne me choque pas outre mesure (bien que le break dans ce cas me choque pour la raison que je m'apprête à exprimer)

    Par contre, si
    • le compteur (l'itérateur) est défini avant d'entrer dans la boucle ou si
    • il existe une condition de sortie de boucle autre que la seule condition de la boucle (le fameux if(condition_de_sortie) de mon exemple) ou si
    • la gestion même du compteur (de l'itérateur) est soumise à condition
    les boucles "tant que" (while() ) ou "jusqu'à ce que" ( do... while() ) me semblent clairement mieux adaptées

    J'associe énormément l'amputation d'une des composantes de la boucle pour au fait de multiplier les conditions de sorties ou les actions d'itérations en leur sein, avec des code proches de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(int i=0; i<MAXITER, found = false; ++i)
    ou de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(int i = 0;i<MAXITER; ++i,--j)
    ou encore de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(int i = 0, int j=MAXITER;i<MAXITER; ++i)
    ou pire encore d'une combinaison des différents points

    Je sais parfaitement bien que chacune de ces syntaxe est légale et autorisée, mais, et ce n'est encore que mon avis personnel, elles augmentent le risque de mauvaise interprétation du code (il est facile de "zapper" le fait que j est décrémenté ou que l'on teste found) sans apporter d'avantage significatif.

    A ce rythme, je préfères, et de loin, une bonne vieille boucle "tant que"
    Bref, ça documente autant que ça fait "moche"
    Justement, je trouve que, loin de documenter le code, cela ne fait que l'obfuquer un peu d'avantage...

    Mais je suis peut être victime de mon approche "une ligne, une instruction" un peu trop étriquée

    Maintenant, j'ai conscience d'aller à contre courent de Stroutrup qui plaide même pour l'utilisation généralisée de
    et je concède à tous la possibilité de penser différemment

    [EDIT]Ou peut-être est-ce au contraire parce que la représentation d'algorithmes que j'utilise me permet d'éviter les écueils de tels sucres syntaxiques
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 26/07/2007, 19h09
  2. Vector , passage de double entre vector
    Par croumir dans le forum SL & STL
    Réponses: 3
    Dernier message: 14/06/2007, 22h39
  3. Réponses: 7
    Dernier message: 22/10/2006, 18h51
  4. [VB6] [MDI] Signaler la fermeture d'une fille à la mère
    Par cpri1shoot dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 13/04/2004, 08h57
  5. Réponses: 2
    Dernier message: 11/07/2003, 18h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo