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 :

class avec plusieurs paramètres template, et fonction amie


Sujet :

C++

  1. #1
    Candidat au Club
    Inscrit en
    Novembre 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Novembre 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut class avec plusieurs paramètres template, et fonction amie
    Bonjour,

    Me revoilà avec un problème à peine différent de celui que j'ai posté ici il y a quelques jours, et pourtant, malgré mes recherches, je suis bien en peine pour trouver la solution tout seul...

    J'ai deux classes conteneurs très proches :
    - L'une est à taille statique : sa capacité lui est passée par un paramètre template lors de l'instanciation, elle ne peut donc plus jamais varier ensuite. Le template de cette class prend donc deux paramètres : le type d'objet à contenir, et la capacité du conteneur.
    - L'autre est à taille dynamique : la capacité du conteneur varie au cour de la vie d'une instance. Le template de la classe prend donc un seul et unique paramètre : le type d'objet à contenir.

    Lorsque ces deux conteneurs possèdent le même type d'objet, j'aimerai pouvoir les concaténer et renvoyer le résultat dans un conteneur dynamique. Et je voudrai faire ça avec une fonction libre, amie des deux classes à la fois.

    Malheureusement, je ne trouve pas la syntaxe adéquate, aucune de mes tentatives ne compile (Borland c++builder 6). Quelqu'un à une idée ?


    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
     
    template <class Objet, int Taille> class ConteneurStatique;
    template <class Objet> class ConteneurDynamique;
     
    template <class Objet, int Taille>
    const ConteneurDynamique<Objet> Add (const ConteneurDynamique<Objet> &DynamicData, const ConteneurStatique<Objet, Taille> &StaticData) {
      ConteneurDynamique<Objet> Result;
      // ... utilise les données protégées des arguments pour déterminer Result ...
      return Result;
    }
     
    template <class Objet, int Taille>
    class ConteneurStatique {
      public:
        // Ok
        friend const ConteneurDynamique<Objet> Add<> (const ConteneurDynamique<Objet> &DynamicData, const ConteneurStatique<Objet, Taille> &StaticData);
      protected:
        Objet Data[Taille];
    };
     
    template <class Objet>
    class ConteneurDynamique {
      public:
        // E2401 Invalid template argument list
        template <int Taille>
        friend const ConteneurDynamique<Objet> Add<> (const ConteneurDynamique<Objet> &DynamicData, const ConteneurStatique<Objet, Taille> &StaticData);
     
      protected:
        Objet *Data;
    };
     
     
    int main(int argc, char *argv[]) {
      ConteneurDynamique<int> Data1;
      ConteneurStatique<int, 10> Data2;
      ConteneurDynamique<int> R = Add (Data1, Data2);
      return 0;
    }

  2. #2
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Points : 311
    Points
    311
    Par défaut
    J'ai jeté un oeil à ton code pourquoi met tu sans le <> chez moi sa compile.

  3. #3
    Candidat au Club
    Inscrit en
    Novembre 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Novembre 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Parce que c'est la syntaxe qui va bien

    Du moins, pour la déclaration d'amitié de Add avec la class ConteneurStatique, le Add<> ou Add<Objet> est obligatoire sinon ca compile pas chez moi. Je te renvoie aux réponses qui m'ont été données sur le sujet :
    http://www.developpez.net/forums/d10...fonction-amie/

    T'as vérifié si tu pouvais vraiment acceder au membre Data de chaque argument ? C'est quoi ton compilateur ?

  4. #4
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    friend ... Add<Objet,Taille> ?

    Sur .Net 2010, ça compile, mais va savoir pour Borland C++ Builder 6... Ce compilateur n'est pas vraiment reconnu pour son support correct des standard. En fait, il compile un dialecte du C++, pas du C++.

    Peut-être faudrait-il voir avec la communauté Borland ? (si une telle communauté existe, bien sûr).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  5. #5
    Candidat au Club
    Inscrit en
    Novembre 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Novembre 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    ca marche pas non plus malheureusement

    Si vraiment builder respecte si peu la norme que tu le dis, il est temps que je le change. Mais je suis complètement perdu, et c'est frustrant de devoir laisser la programmation de coté pour passer du temps a choisir un soft et à s'adapter à son interface. Ca fera surement l'objet d'un post un de ces quatre.

    En attendant, merci à tous les deux de vous être penché sur mon problème.

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    La solution la plus simple serait encore de ne pas utiliser l'amitié...

    Il suffit de mettre une fonction back_insert dans ta classe ConteneurDynamique, en publique, qui auraient pour fonction d'ajouter des éléments à la fin du conteneur puis de créer une fonction Add qui appellerait cette fonction back_insert.

    Au fait, boost::array pour ton tableau statique ?

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par sleepless Voir le message
    ca marche pas non plus malheureusement

    Si vraiment builder respecte si peu la norme que tu le dis, il est temps que je le change. Mais je suis complètement perdu, et c'est frustrant de devoir laisser la programmation de coté pour passer du temps a choisir un soft et à s'adapter à son interface. Ca fera surement l'objet d'un post un de ces quatre.

    En attendant, merci à tous les deux de vous être penché sur mon problème.
    Le problème étant que si tu te sers des librairies livrées avec, tu risques d'avoir des problèmes.

    C'est bien Borland C++ Builder 6.0 ? Si c'est le cas, alors le compilateur est effectivement très daté. Dr. Dobbs, en 2003, a évalué sa correspondance au coeur du standard à 92%, lorsque les autres compilateurs du marché oscillait entre 96 et 99% (98% pour Visual C++ 7.1). Pour comparaison, Visual C++ 6.0, compilateur pré-standard, était à 83% sur le même test.

    Les compilateurs récents s'étant encore amélioré, il devient fortement en retard.

    Bien évidemment, le point d'achoppement des compilateurs est souvent les templates. Si on veut jouer avec eux correctement, il faut un compilateur récent.

    Cependant, comme je le disais en introduction, tu risques fort d'avoir des problèmes.

    Il existe pourtant une solution simple : changer le design de tes classes, et passer par des itérateurs - comme le fait la librairie standard. Ou utiliser boost - dont certaines parties fonctionnent correctement sur BC++ (à noter que ce compilateur ne bénéficie pas vraiment du meilleur support qui soit; il est même très en retard sur les autres compilateurs).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Je croyais que l'amitié et les templates était impossible? tout simplement car on ne peut pas être ami avec tout le monde.
    Homer J. Simpson


  9. #9
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Il suffit de donner un compte Facebook à ta classe pour qu'elle soit amie avec tout le monde, non ?

    Plus sérieusement, c'est tout à fait possible. J'utilise parfois la déclaration suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <typename T>
    class SerializableObject : public T
    {
    private:
        template<typename Stream> friend Stream& operator>> (Stream& out, T& interface);
        template<typename Stream> friend Stream& operator<< (Stream& out, const T& interface);
    };
    (dite moi si c'est mal !)

    Ce qui me permet de pouvoir facilement ajouter ces opérateurs pour n'importe quel flux (std::iostream, qDebug(), QDataStream, etc.) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <>
    std::ostream& operator<< (std::ostream& stream, const SerializableObject& interface)
       { ... }
     
    template <>
    QDebug& operator<< (QDebug& stream, const SerializableObject& interface)
       { ... }
     
    template <>
    QDataStream& operator<< (QDataStream& stream, const SerializableObject& interface)
       { ... }
    (sous gcc 4.5)

    cf Vandevoorde, chap 8.4.2, Friend template

  10. #10
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Astraya Voir le message
    Je croyais que l'amitié et les templates était impossible? tout simplement car on ne peut pas être ami avec tout le monde.
    C'est effectivement quelque chose qu'on entend dire régulièrement. Mais dans les faits, c'est tout à fait possible. On peut même être ami avec une spécialisation partielle d'une classe template.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template <class T> callable { ... };
    template <class R, class A> callable<R(A)> { ... };
     
    class X
    {
      // ami avec la spécialisation, mais pas avec la classe
      // template callable<> générique. 
      template <class R, class A> friend class callable<R(A)>;
    };
    La seule condition est que la spécialisation (partielle ou complète) doit être déclarée avant la clause friend.

    Si je ne me trompe nulle part dans la syntaxe...

    Il faut en outre faire attention : dès lors qu'on est ami avec une classe template, rien n'empêche un malandrin de spécialiser cette classe pour faire des choses pas bien.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  11. #11
    Candidat au Club
    Inscrit en
    Novembre 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Novembre 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Pour le problème du compilateur qui ne suis pas bien la norme, je vais essayer code::blocks dès que j'ai un peu de temps. Et je me passerai de l'amitié d'ici là (ou alors j'envisagerai sérieusement l'option facebook^^).

    Mais en attendant, j'aimerai confronter certains de mes choix, (sans doutes discutables) concernant l'amitié et les conteneurs standard à vos critiques.

    Contexte : programmeur amateur et essentiellement autodidacte. Aucune contrainte sauf le désir de faire aboutir mon projet, c'est un hobby pour moi. Sûrement plein de mauvaises habitudes acquises au fil des années sans personne pour lire/critiquer mes codes. C'est un bonheur pour moi que d'avoir l'occasion de parler avec des pros et des amateurs plus aguerris que moi, merci encore à ceux qui postent tous les jours sur ce forum.

    Mon projet concerne le poker, et vise à répondre à certaines questions stratégiques en utilisant des simulations de Monte Carlo et la théorie des jeux. Lorsqu'on utilise la théorie des jeux pour résoudre des problèmes de poker, beaucoup de situations impliquent un tel volume de combinaisons différentes qu'une simulation, même limitée à un petit échantillons de cas, nécessitera des jours voir des semaines de calcul. L'optimisation des algorithmes et des structures de données est donc primordiale pour raccourcir ce temps.

    Apres plusieurs mois à travailler sur l'évaluateur de main à 7 cartes, c'est à dire l'algo qui donne une "note" à une main de poker, permettant ainsi de comparer la force d'une main à celle des adversaires, je suis enfin arrivé à un résultat performant. Mais il est freiné par mes objets de base (deck, card, hand, board, etc.) qui ne profitent pas autant de la mémoire cache qu'ils le pourraient. Je suis donc en train de tout refaire (heureusement ça ne nécessite aucun changement d'interface), et j'en profite au passage pour factoriser ce qui peut l'être avec les templates.

    Pourquoi je n'utilise pas la STL ni Boost :
    Pour des structure de données qui devront supporter plusieurs millions d'accès par seconde et pendant longtemps, il me semble que je suis dans un des rares cas ou il devient intéressant de coder soit même des conteneurs "sur mesure", pour pouvoir tout contrôler et avoir les meilleurs performances possibles. Ais-je tords ? Faire passer les performances en priorité devant la solidité du code et le temps de mise en oeuvre vous parait-il une aberration dans mon cas ?

    Pourquoi j'utilise l'amitié :
    Toujours pour les performances, par exemple si j'ai une "class Foo" et une fonction libre "operator+(const Foo1&, const Foo2&)" qui va avec, ça me fait enrager d'appeler les accesseurs de Foo dans la fonction libre. Pour chaque accesseur utilisé, ça fait un empilement des registres + un saut + un dépilement des registres, qui pourraient être évités en accédant directement aux données privées de Foo grâce à l'amitié. Et je n'ai pas l'impression de faire quelque chose de "contre nature" avec cette déclaration d'amitié, puisque la fonction "operator+(const Foo1&, const Foo2&)" pourrait même être une fonction membre de "Foo" (elle n'est sortie de la class que pour des raison de style et de lisibilité du code). D'un autre coté, peut être que le gain apporté par l'accès direct aux membres privés de Foo sera négligeable même sur des millions d'appels (notamment si les accesseurs de Foo sont inlinés), qu'en pensez-vous ?

  12. #12
    Candidat au Club
    Inscrit en
    Novembre 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Novembre 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    @Emmanuel Deloget : oups, emporté par mon élan, j'ai oublié de répondre à tes questions. Oui c'est bien borland c++ builder 6, et non, je n'utilise plus la VCL : ca fait quelques années que j'ai lu les doutes des programmeurs au sujet de sa pérennité. Je peux donc espérer changer d'edi et de compilo sans trop de dommage collatéraux. Pour le design de mes classes, je te renvoie à mes explication dans mon précédent post.

  13. #13
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par sleepless Voir le message
    Pourquoi j'utilise l'amitié :
    Toujours pour les performances, par exemple si j'ai une "class Foo" et une fonction libre "operator+(const Foo1&, const Foo2&)" qui va avec, ça me fait enrager d'appeler les accesseurs de Foo dans la fonction libre. Pour chaque accesseur utilisé, ça fait un empilement des registres + un saut + un dépilement des registres, qui pourraient être évités en accédant directement aux données privées de Foo grâce à l'amitié. Et je n'ai pas l'impression de faire quelque chose de "contre nature" avec cette déclaration d'amitié, puisque la fonction "operator+(const Foo1&, const Foo2&)" pourrait même être une fonction membre de "Foo" (elle n'est sortie de la class que pour des raison de style et de lisibilité du code). D'un autre coté, peut être que le gain apporté par l'accès direct aux membres privés de Foo sera négligeable même sur des millions d'appels (notamment si les accesseurs de Foo sont inlinés), qu'en pensez-vous ?
    euh non v_v, tu fais des choses très sale
    Pour info, la bonne structure pour les operator+ etc ets la suivante :

    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
     
    class foo
    {
       public:
     
       foo& operator+=(foo const& b)
      {
        // calcul *this = *this + b -- comme on est dans foo, pas de proble;e d'accesseur
      }
       private:
       // plein de membres
    };
     
    foo operator+(foo const& a, foo const& b )
    {
      foo tmp(a);
      tmp += b;
      return tmp;
    }
    Les vrais compilateurs inlinent tous ca depuis au moins 1515. C'est typiquement de la premature optimisation.

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

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Pour des structure de données qui devront supporter plusieurs millions d'accès par seconde et pendant longtemps, il me semble que je suis dans un des rares cas ou il devient intéressant de coder soit même des conteneurs "sur mesure", pour pouvoir tout contrôler et avoir les meilleurs performances possibles. Ais-je tords ? Faire passer les performances en priorité devant la solidité du code et le temps de mise en oeuvre vous parait-il une aberration dans mon cas ?
    Oui. Car tu les battras pas.

    Pour l'op + la bonne forme est celle que te montre Joel, cherche pas à faire des trucs de sioux sinon ça te pétera dans les doigts. (ici tu profites de la symétrie etc etc).
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  15. #15
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par sleepless Voir le message
    Pourquoi je n'utilise pas la STL ni Boost :
    Pour des structure de données qui devront supporter plusieurs millions d'accès par seconde et pendant longtemps, il me semble que je suis dans un des rares cas ou il devient intéressant de coder soit même des conteneurs "sur mesure", pour pouvoir tout contrôler et avoir les meilleurs performances possibles. Ais-je tords ? Faire passer les performances en priorité devant la solidité du code et le temps de mise en oeuvre vous parait-il une aberration dans mon cas ?
    Tu sais, une bibliothèque utilisée et observée sous toutes les coutures telle que boost ou la STL sera, forcément, de bien meilleure facture qu'une bibliothèque développée "dans ton coin", et ce sur tous les aspects.

    La raison est toute simple: il y a beaucoup plus de gens qui en observent le code, et qui peuvent donc apporter de meilleures solutions .

    A titre d'exemple: tu risque, naïvement, d'augmenter la taille du tableau dynamique à chaque ajout d'élément, ce qui implique un jeu d'allocation / libération de la mémoire chaque fois que tu va décider d'ajouter un élément.

    L'implémentation dans la STL que l'on retrouve le plus souvent va quant à elle (presque) doubler la taille du tableau uniquement quand c'est nécessaire.

    Cela ne coute "que" la place nécessaire pour maintenir en mémoire le nombre d'objets au delà duquel il faut envisager d'augmenter la taille, mais cela permet d'amortir le cout (tant en mémoire qu'en temps) de l'augmentation de cette taille, vu qu'elle n'a plus lieu de manière systématique lors de l'insertion.

    Le mieux de l'histoire, c'est que, plus le nombre d'éléments contenu sera important, plus tu gagnera du temps à l'insertion, car moins souvent tu te retrouvera face à la nécessité d'augmenter la taille.

    Je n'ai aucune honte à dire que je n'y aurais sans doute pas pensé tout seul, et toi
    Pourquoi j'utilise l'amitié :
    Toujours pour les performances, par exemple si j'ai une "class Foo" et une fonction libre "operator+(const Foo1&, const Foo2&)" qui va avec, ça me fait enrager d'appeler les accesseurs de Foo dans la fonction libre. Pour chaque accesseur utilisé, ça fait un empilement des registres + un saut + un dépilement des registres, qui pourraient être évités en accédant directement aux données privées de Foo grâce à l'amitié. Et je n'ai pas l'impression de faire quelque chose de "contre nature" avec cette déclaration d'amitié, puisque la fonction "operator+(const Foo1&, const Foo2&)" pourrait même être une fonction membre de "Foo" (elle n'est sortie de la class que pour des raison de style et de lisibilité du code). D'un autre coté, peut être que le gain apporté par l'accès direct aux membres privés de Foo sera négligeable même sur des millions d'appels (notamment si les accesseurs de Foo sont inlinés), qu'en pensez-vous ?
    Je ne reviendrai pas sur la "bonne" manière de faire un opérateur +, car tout a été dit par Joêl, mais, effectivement, le fait d'inliner l'opérateur += et l'opérateur + aura pour résultat que tu évitera les retards liés à l'appel de fonctions, et ce, même si, pour une raison qui lui est propre, le compilateur décide au final de ne pas inliner l'une ou l'autre.

    En outre, il faut te dire que, sauf exception, le code des classes template sera d'office inliné, ne serait-ce que parce que le compilateur doit attendre de savoir quel type de donnée est réellement manipulé avant de pouvoir fournir le code binaire correspondant
    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

  16. #16
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par Goten Voir le message
    Pour des structure de données qui devront supporter plusieurs millions d'accès par seconde et pendant longtemps, il me semble que je suis dans un des rares cas ou il devient intéressant de coder soit même des conteneurs "sur mesure", pour pouvoir tout contrôler et avoir les meilleurs performances possibles. Ais-je tords ? Faire passer les performances en priorité devant la solidité du code et le temps de mise en oeuvre vous parait-il une aberration dans mon cas ?
    Oui. Car tu les battras pas.
    Je suis plus circonspect que toi. J'ai eu il y a quelques années une discussion (houleuse) sur ce sujet précis avec Dave Eberly, et j'en suis arrivé à comprendre et approuver son point de vue.

    Les conteneurs de la C++SL sont génériques. En tant que tels, et même si des efforts importants ont été fait pour améliorer les performances, il y a quand même de fortes chances qu'ils ne soient pas aussi performants qu'un code moins générique et complètement dédié à une tâche particulière. Dire le contraire, ce serait prétendre que "one size fits all", et que SQL devrait être utilisé par Google pour stocker les infos qu'il récupère pour chaque page d'un site. Google n'est pas d'accord avec ça, et préfère justement une approche NoSQL.

    Quoi qu'il en soit, ce genre d'informations (faut-il le faire ?) est un problème d'optimisation : une décision ne peut être prise qu'après avoir 1) vérifier que le code actuel posait des problèmes de performances 2) implémenté une autre solution 3) vérifier que cette solution est plus rapide.

    Il existe de nombreux cas dans lesquels les conteneurs de la C++SL peuvent être mis au rencard pour implémenter d'autres conteneurs. Prenons un cas simple : je dois stocker de manière contiguë 16 milliards d'objets, chaque objets faisant 64 bytes. Si je les garde tous en mémoire dans un std::vector<>, je risque fort d'avoir des soucis même sur mon hyper-puissant octocore avec 24 GB de mémoire (non, je n'ai pas une telle machine ).

    Puisqu'il est tout à fait légitime de se poser la question dans ce cas, pourquoi ne le serait-il pas dans certains autres cas particuliers ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  17. #17
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Je suis plus circonspect que toi. J'ai eu il y a quelques années une discussion (houleuse) sur ce sujet précis avec Dave Eberly, et j'en suis arrivé à comprendre et approuver son point de vue.

    Les conteneurs de la C++SL sont génériques. En tant que tels, et même si des efforts importants ont été fait pour améliorer les performances, il y a quand même de fortes chances qu'ils ne soient pas aussi performants qu'un code moins générique et complètement dédié à une tâche particulière. Dire le contraire, ce serait prétendre que "one size fits all", et que SQL devrait être utilisé par Google pour stocker les infos qu'il récupère pour chaque page d'un site. Google n'est pas d'accord avec ça, et préfère justement une approche NoSQL.

    Quoi qu'il en soit, ce genre d'informations (faut-il le faire ?) est un problème d'optimisation : une décision ne peut être prise qu'après avoir 1) vérifier que le code actuel posait des problèmes de performances 2) implémenté une autre solution 3) vérifier que cette solution est plus rapide.

    Il existe de nombreux cas dans lesquels les conteneurs de la C++SL peuvent être mis au rencard pour implémenter d'autres conteneurs. Prenons un cas simple : je dois stocker de manière contiguë 16 milliards d'objets, chaque objets faisant 64 bytes. Si je les garde tous en mémoire dans un std::vector<>, je risque fort d'avoir des soucis même sur mon hyper-puissant octocore avec 24 GB de mémoire (non, je n'ai pas une telle machine ).

    Puisqu'il est tout à fait légitime de se poser la question dans ce cas, pourquoi ne le serait-il pas dans certains autres cas particuliers ?
    Je suis, d'accord avec toi, mais j'y mettrais cependant un bémol:

    Oui, une implémentation moins générique peut prendre l'avantage sur la SL, mais... à la condition expresse qu'elle soit envisagée:
    1- pour une raison cohérente et indiscutable
    2- parce que l'on rencontre, effectivement, des problèmes de performances avec la SL
    3- (et surtout) par quelqu'un qui maitrise suffisamment l'optimisation pour arriver à faire mieux.

    Les deux premières conditions sont, on va le dire en tout cas, assez faciles à remplir, mais la troisième, c'est une autre paire de manches

    Je ne mets en cause la compétence de personne en particulier, mais le nombre de gens qui seront effectivement susceptibles de faire mieux ne sont pas vraiment nombreux, et je crains que l'on puisse, de toutes façons, disqualifier pour le titre tout ceux qui ne maitrisent pas parfaitement le langage .

    Combien de gens sur le forum pourraient ils prétendre honnêtement être en mesure de faire mieux :quesion:

    Je dois avouer que je n'y arriverai sans doute moi-même qu'avec un peu (beaucoup) d'aide et après un temps de mise au point relativement important

    Et pourtant, je n'ai jamais caché que l'algorithmique est mon domaine, et je connais les subtilité du C et du C++
    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

  18. #18
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Combien de gens sur le forum pourraient ils prétendre honnêtement être en mesure de faire mieux :quesion:

    Je dois avouer que je n'y arriverai sans doute moi-même qu'avec un peu (beaucoup) d'aide et après un temps de mise au point relativement important

    Et pourtant, je n'ai jamais caché que l'algorithmique est mon domaine, et je connais les subtilité du C et du C++
    Si je devais répondre pour moi, je dirais : ben, euh, peut-être en fait mais, euh, j'en suis quand même pas tout à fait sûr. Enfin bon, au bout d'un (long) moment, j'obtiendrais certainement quelque chose

    c'est vrai que ça demande une grande maîtrise et beaucoup de temps devant soi.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  19. #19
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Si je devais répondre pour moi, je dirais : ben, euh, peut-être en fait mais, euh, j'en suis quand même pas tout à fait sûr. Enfin bon, au bout d'un (long) moment, j'obtiendrais certainement quelque chose

    c'est vrai que ça demande une grande maîtrise et beaucoup de temps devant soi.
    Nous sommes donc bien d'accord que c'est, encore une fois, le genre de pratique à ranger dans la catégorie des "si on ne peut vraiment pas faire autrement"

    La réaction de Goten est donc, a priori du moins, tout à fait justifié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

  20. #20
    Candidat au Club
    Inscrit en
    Novembre 2010
    Messages
    11
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations forums :
    Inscription : Novembre 2010
    Messages : 11
    Points : 4
    Points
    4
    Par défaut
    Ca fait plaisir de voir autant de réactions.

    Je me laisse facilement convaincre par Joel au sujet de l'amitié : c'est plus simple à maintenir sans, et on peut espérer que le compilateur va optimiser. Je trouve ça juste frustrant que ça ne soit pas écrit explicitement dans le code. Il me semble même avoir lu que l'utilisation de "inline" était une simple indication qui n'obligeait en rien le compilateur à inliner quoi que ce soit (je me trompe ?).

    Sinon, les "vrais compilateurs", c'est lesquels ?

    Par contre, je vais essayer de résister un peu en ce qui concerne la STL. Je m'attendais à ce qu'on m'objecte que le gain de performance ne valait pas le coup par rapport au temps passé à réinventer la roue (et à la débugger). Mais certainement pas à ce qu'on me présente l'exercice comme un challenge de haute volée (et donc hors de mes capacités). Comment une lib aussi générale et riche en fonctionnalité que la STL peut elle performer mieux que des conteneurs minimalistes et dédiés à une utilisation bien précise ?

    Je vais être têtu, et je promets de revenir d'ici quelques semaines avec un benchmark pour comparer les deux dans le contexte de mon appli. Probablement une humiliation publique en perspective, mais si c'est le cas, au moins ça m'aura vacciné contre l'excès de confiance en moi (et ça m'aura fait progresser avec les templates).

    Et pour l'implémentation de mon conteneur "dynamique" (si si, un peu!) non, je ne fait pas une allocation à chaque ajout d'un nouvel élément, le résultat serai catastrophique niveau performance. J'utilise une méthode "SetSize()" pour définir la capacité du tableau, et il revient à l'appelant de ne pas changer la taille à tout bout de champ. Concrètement, il est exceptionnel que la taille change en court de route (et ça n'arrive jamais dans la boucle principale).

Discussions similaires

  1. class template et fonction amie
    Par sleepless dans le forum C++
    Réponses: 5
    Dernier message: 19/11/2010, 13h37
  2. Appel d'une fonction avec plusieurs paramètres
    Par kazarn dans le forum Général JavaScript
    Réponses: 7
    Dernier message: 06/06/2009, 18h55
  3. créer une fonction avec plusieurs paramètres
    Par SHERPAE dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 06/01/2009, 17h41
  4. Aide pour déclarer fonction avec plusieurs paramètres de sortie
    Par tonioj41 dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 16/01/2008, 11h06
  5. [Système] Fonction avec plusieurs paramètres optionnels
    Par cerede2000 dans le forum Langage
    Réponses: 1
    Dernier message: 25/05/2007, 14h36

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