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

Langage C++ Discussion :

Un tableau multitype est-il rentable?


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Un tableau multitype est-il rentable?
    Bonjour,
    J'ai réalisé un patite classe(template) permettant de stocker des objet de plusieurs types en évitant les pointeurs, l'allocation dynamique, les fonctions virtuelles...
    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    template<class T>
    struct MultyTypesContainer;
     
     
     
    template<class T>
    struct SingleTypeContainer
    {
        void insert(const T& val)
        {
             set_.insert(val);
        }
     
        template<class Func>
        Func call_for_each(Func f)
        {
            return std::for_each(set_.begin(), set_.end(), f);
        }
     
    private:
    	std::set<T> set_;
    };
     
     
    template<class Head, class Tail>
    struct MultyTypesContainer<Loki::Typelist<Head,Tail> >
    {
        typedef typename Loki::Typelist<Head,Tail> TList;
        enum{size = Loki::TL::Length<TList>::value};
        typedef typename Loki::GenScatterHierarchy<TList,SingleTypeContainer> MultyTypesContainerImplementation;
        MultyTypesContainerImplementation impl_;
        template<class Func, int i>
        Func call_for_each(Func f, Loki::Int2Type<i>)
        {
            f = Loki::Field<i>(impl_).call_for_each(f);
    	return call_for_each(f, Loki::Int2Type<i-1>());
        }
     
        template<class Func>
        Func call_for_each(Func f, Loki::Int2Type<0>)
        {
    	return Loki::Field<0>(impl_).call_for_each(f);
        }
     
    public:
        template<class T>
        void insert(const T& val)
        {
    	impl_.SingleTypeContainer<T>::insert(val);
        }
        template<class Func>
        Func call_for_each(Func f)
        {
    	return call_for_each(f, Loki::Int2Type<size-1>());
        }
    };
    Je voulais savoir si vous pensez qu'une classe comme celle-ci peut être utile ou au contraire qu'elle pourra encombrer un plus ma corbeille de projets ratés ?

    PS: En appelant 500000 fois une fonction(membre) vide a partir d'un ensemble de 1000 objets j'ai entre 7% et 8% de gain de vitesse.

    EDIT:
    En fait, pour éviter d'écrire des tonnes de foncteur j'ai fait un petit macro
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    #define CALL_MEMBER_FUNCTION0(function) \
                struct \
    	    { \
    		template<class T>\
    		void operator()(T& obj) \
    		{\
    	            obj.function(); \
    	        }\
    	    }
    et je l'utilise avec un typedef :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef CALL_MEMBER_FUNCTION0(get_statistics) GetSatisticsFunctor;
     
    typedef MultyTypesContainer<Classe1, Classe2> Conteneur;
     
    Conteneur stats;
    stats.call_for_each(GetSatisticsFunctor());
    Par contre je peux pas faire mon typedef(le premier) dans un fonction : les classes locales ne peuvent pas avoir de fonctions membres template.

    PS2 : J'ai aussi codé un iterateur mais bon, vu ses performances, je vais éviter de le poster...
    Dernière modification par Invité ; 29/01/2010 à 16h42.

  2. #2
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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
    Par défaut
    Du point de vue d'un architecte, quelques questions :

    1) dans quel cas est-ce que je peux avoir besoin d'une telle classe ? As-tu identifier un besoin clair (parce que la programmation pour la programmation, ça a quand même des limites... )?

    2) Comment puis-je l'utiliser, une fois que j'ai mis des carottes et des presse-papiers dans le même sac ?

    3) Comment faire pour récupérer une valeur dans ce conteneur ? (parce que bon, contenir des valeurs, c'est bien, mais un jour ou un autre il faudra les traiter...)

    4) Que faire si les différents types stockés n'ont pas la même interface ? (c'est nécessaire pour l'utilisation du foncteur que tu donnes en exemple. Plus généralement, si tu comptes utiliser call_for_each() sur le conteneur entier, le foncteur que tu passes en paramètre
    * doit être capable de retrouver, via par exemple des traits, les caractéristiques des différents types d'objet manipulés
    * ou, au moins, être spécialisé pour traiter chacun des types d'objet manipulés.)

    5) Si les différents types stockés ont la même interface, pourquoi est-ce le cas ?

    D'autres questions peuvent survenir dans mon esprit torturé d'un instant à l'autre...
    [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.

  3. #3
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Quelle différence avec boost::variant ? C'est multi-type (disons prédéfinis). L'accès se fait via des visiteurs.
    Je pense pas avoir besoin de plus que ça. D'ailleurs, comme le souligne Emmanuel, après on sait plus les traiter, non ?

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Tout d'abord merci pour vos réponse.
    1) Je pensais avoir quelques cas:
    *si on veut conserver le type exacte d'un objet(notamment lorsque on veut appeler un fonction utilisant de deux ces objets et mettant en place un comportement différent en fonction de leurs types; on pourrait utiliser un double dispatcher mais ça demanderait au mieux un static_cast, au pire un dynamic)
    *si on veut éviter la surcharge de coût à l'éxecution

    2)Je pensais aussi rajouter des accesseurs pour récupérer en fonction du type

    3)Par un foncteur, non?

    4)Honnêtement, je n'y avais pas pensé, mais c'est un bonne idée

    5)Ca rejoint un peut tout les autres points

    D'après ce que j'ai compris, boost::variant ne peut pas contenir à la fois "hello_world" et 5.0f .

    En fait, ce "conteneur" part de ce principe : "il est inutile de faire du dynamique quand l'on peut faire du statique"

    J'espère avoir été le plus explicite possible.Vos conseils vont sans doute me permettre de m'améliorer(ca sera pas plus mal).

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    Boost.Variant est une 'union'. Ensuite tu peux avoir un conteneur classique (list, vector, map, etc.) de Boost.Variant pour avoir un conteneur hétérogène.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Alors oui, c'est pour l'instant le même fonctionnement(enfin un conteneur de boost::variant contient toutes les opérations du mien). Mais je pourrais "améliorer" le mien en rajoutant un fonction pour obtenir tout les objet d'un (ou plusieurs) type(s).

    Je rajoute à mes cas d'utilisation : il est parfois désirable d'obtenir un conteneur triée en fonction du type(exact) des objets qu'il contient.

  7. #7
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Un conteneur de choses qui n'ont pas grand chose en commun c'est rarement une bonne solution.

    Un autre cas de figure est quand tu veux l'équivalent d'un type de donnée algébrique (une sorte d'enum qui a mangé des épinards, cf ce qu'on fait en OCaml et Haskell par exemple pour ça), boost::variant est parfait.

    MAIS, si tu as vraiment besoin d'un conteneur pouvant contenir vraiment n'importe quoi, je te conseille de jeter un oeil à boost::any (donc par exemple un std::vector<boost::any> dans ton cas). Par ailleurs, si l'implémentation de boost.any t'intéresse, tu peux jeter un oeil à cet article. Cela devrait d'ailleurs t'aider à savoir si c'est vraiment ce dont tu as besoin dans ton cas ou alors s'il te faudrait plutôt un container par type avec une classe qui dispatcherait les tentatives de récupération grâce à un mécanisme basique se basant sur les templates.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Un conteneur de choses qui n'ont pas grand chose en commun c'est rarement une bonne solution.

    Je n'ai sans doute pas été très clair dans mon premier post. Ce conteneur est fait pour des objets qui ont une interface commune. Je vais donner quelques exemples :
    *On a une hiérarchie de classe avec un class Shape définissant des méthodes virtuels pures , des classes filles Square et Circle les implémentant et un vector<Shape*>. On aussi plusieurs fonctions intersect (Square-Square, Square-Circle,...). Pour éviter des downcast à répétition on supprime Shape et le vector<Shape*> pour les remplacer par un conteneur<Square, Circle>.

    *On a une classe abstraite GameObject avec, comme classes filles, Monster et Ground. On veut absolument que Monster soit dessiné après Ground. Dans ce cas là on ne peut pas faire un vector<GameObject*>. Je pense que mon conteneur est un bonne alternative.

    Basiquement, je m'était fixée cette classe comme un exercice, pour vérifier si les templates pouvait parvenir a faire le même polymorphisme que l'héritage

    un container par type avec une classe qui dispatcherait les tentatives de récupération grâce à un mécanisme basique se basant sur les templates.
    Ce n'est pas ce que j'ai fais? Sinon pourrais-tu expliquer un peu plus clairement, s'il te plais ?

    Merci d'avance

  9. #9
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Je te conseille la lecture intégrale de l'article dont j'ai donné un lien dans mon précédent post. Il traite justement le problème/la séparation entre polymorphisme template / polymorphisme d'héritage.

    Sinon, si tu veux éviter le conteneur de Shape* (ce qui est la pratique courante hein, si tu as des downcasts à faire à un moment c'est que tu t'es trompé en cours de route, tu n'offres pas assez dans l'interface, ou tu t'y es mal pris ?), c'est boost::variant l'alternative viable. Et si tu utilises boost variant, tu n'as même plus besoin de ta classe de base Shape, car l'interface est cette fois garantie par le polymorphisme statique fourni par les templates.

    Donc, pour résumer, je te conseille un peu de lecture :
    http://alp.developpez.com/tutoriels/type-erasure/
    http://cpp.developpez.com/faq/cpp/in...=polymorphisme (la majeure partie de ces Q/R)

    Ca t'oriente justement sur quand utiliser l'héritage, simplement, et quand est-ce que les templates peuvent nous aider avantageusement par rapport à l'héritage, etc. Et comment bien marier les deux.

  10. #10
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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
    Par défaut
    Citation Envoyé par Joe Dralliam Voir le message
    Je n'ai sans doute pas été très clair dans mon premier post. Ce conteneur est fait pour des objets qui ont une interface commune. Je vais donner quelques exemples :
    *On a une hiérarchie de classe avec un class Shape définissant des méthodes virtuels pures , des classes filles Square et Circle les implémentant et un vector<Shape*>. On aussi plusieurs fonctions intersect (Square-Square, Square-Circle,...). Pour éviter des downcast à répétition on supprime Shape et le vector<Shape*> pour les remplacer par un conteneur<Square, Circle>.

    *On a une classe abstraite GameObject avec, comme classes filles, Monster et Ground. On veut absolument que Monster soit dessiné après Ground. Dans ce cas là on ne peut pas faire un vector<GameObject*>. Je pense que mon conteneur est un bonne alternative.

    Basiquement, je m'était fixée cette classe comme un exercice, pour vérifier si les templates pouvait parvenir a faire le même polymorphisme que l'héritage

    Ce n'est pas ce que j'ai fais? Sinon pourrais-tu expliquer un peu plus clairement, s'il te plais ?

    Merci d'avance
    En tant qu'exercice, il y a peut-être un intérêt. En termes d'utilisation, j'ai du mal à le voir. j'avais pensé aux deux cas que tu précises, mais ces deux cas admettent des solutions qui sont bien meilleures et nettement plus ouvertes qu'un conteneur du type de celui que tu présente.

    Prenons le plus simple : le second cas. Il existe un patron de conception (entre autre utilisé par XNA pour gérer les GameComponent) qui rends des services similaires. Je me suis permis de réfléchir dessus et de pondre une première tentative de formalisation il y a déjà quelques mois (cf. cet article sur mon blog) et j'y reviendrais surement pour l'affiner (parce qu'il ne me plait pas vraiment tel que je l'ai défini).

    Le premier cas est à la fois plus simple et plus compliqué. Plus simple parce que la résolution de ce problème passe par la destruction des liens qui peuvent exister entre les classes circle et square. On voit tout de suite que si circle connait square et que square connait circle, on se retrouve dans un cas de dépendance circulaire - pas vraiment bon ça (je pense avoir couvert le sujet maintes fois, donc je ne vais pas revenir dessus ; pour résumer, les dépendances circulaire empêchent le programmeur d'appliquer plusieurs des principes de base du design orienté objet). Ainsi, la méthode qui teste l'intersection est une méthode virtuelle de shape. C'est là que ça se complique, puisque si on veut effectuer l'intersection désirée, il nous faut connaître la topologie des formes utilisée. Dans un langage dynamique, on pourrait utiliser le multi-dispatch, mais cette fonctionnalité n'est pas supportée par le langage C++. Enfin, pas nativement. On peut retrouver ses petits via l'utlisation d'un patron de conception nommé visiteur.

    Le premier niveau de dispatch est représenté par l'appel de la méthode virtuelle intersect. Les implémentations de cette méthode dans les classes filles instancient des visiteurs spécialisés (cette instanciation est notre second niveau de dispatch) et visitent la forme qu'ils doivent traiter. Cette forme cible explore ensuite le visiteur (c'est notre troisième et dernier niveau de dispatch). Les méthodes explore des visiteurs instanciés permettent de code le traitement spécifique à chaque forme en présence.

    shape.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class shape_visitor;
    class shape
    {
    public:
      virtual bool intersect(shape* other) = 0;
      virtual void visit(shape_visitor& visitor) = 0;
    };
    shape_visitor.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class circle;
    class square;
    class shape_visitor
    {
    public:
      virtual void explore(circle* c) { }
      virtual void explore(square* s) { }
    };
    square.h
    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
     
    #include "shape_visitor.h"
    #include "square_intersecting_visitor.h"
    class square : public shape
    {
    public:
      virtual bool intersect(shape* other)
      {
        square_intersecting_visitor visitor(this);
        other->visit(visitor);
        return visitor.result();
      }
      virtual void visitor(shape_visitor& visitor)
      {
        visitor.explore(this);
      }
    };
    circle.h
    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
     
    #include "shape_visitor.h"
    #include "circle_intersecting_visitor.h"
    class circle : public shape
    {
    public:
      virtual bool intersect(shape* other)
      {
        circle_intersecting_visitor visitor(this);
        other->visit(visitor);
        return visitor.result();
      }
      virtual void visitor(shape_visitor& visitor)
      {
        visitor.explore(this);
      }
    };
    square_intersecting_visitor.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include "shape_visitor.h"
    class square_intersecting_visitor : public shape_visitor
    {
      square* m_square;
      bool m_intersect;
    public:
      square_intersecting_visitor(square* s) : m_square(s), m_intersect(false) { }
      bool result() const { return m_intersect; }
      virtual void explore(circle* c);
      virtual void explore(square* s);
    };
    circle_intersecting_visitor.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    #include "shape_visitor.h"
    class circle_intersecting_visitor : public shape_visitor
    {
      circle* m_circle;
      bool m_intersect;
    public:
      circle_intersecting_visitor(circle* c) : m_circle(c), m_intersect(false) { }
      bool result() const { return m_intersect; }
      virtual void explore(circle* c);
      virtual void explore(square* s);
    };
    square_intersect_visitor.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include "square_intersect_visitor.h"
    #include "square.h"
    #include "circle.h"
     
    void square_intersect_visitor::explore(circle* c)
    {
      .. square vs. circle
    }
     
    void square_intersect_visitor::explore(circle* c)
    {
      .. square vs. square
    }
    circle_intersect_visitor.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #include "circle_intersect_visitor.h"
    #include "square.h"
    #include "circle.h"
     
    void circle_intersect_visitor::explore(circle* c)
    {
      .. circle vs. circle
    }
     
    void circle_intersect_visitor::explore(circle* c)
    {
      .. circle vs. square
    }
    Voilà - problème réglé - et de manière à pouvoir simplement être étendu dans le cas ou une nouvelle forme est rajoutée (note : j'ai aussi parlé des problèmes relatifs au pattern visiteur sur mon blog).

    [edit] correction syntaxique, cf plus bas.
    [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
    Invité
    Invité(e)
    Par défaut
    Merci pour vos réponses ça m'a vraiment aidé

  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
    Salut,
    Citation Envoyé par Emmanuel Deloget Voir le message
    <snip>
    square.h
    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
     
    #include "shape_visitor.h"
    #include "square_intersecting_visitor.h"
    class square : public shape
    {
    public:
      virtual bool intersect(shape* other)
      {
        square_intersecting_visitor visitor(this);
        other.visit(visitor);
        return visitor.result();
      }
      virtual void visitor(shape_visitor& visitor)
      {
        visitor.explore(this);
      }
    };
    Ce n'est qu'un détail de syntax, mais, comme tu passe other sous la forme d'un pointeur, ce n'est pas
    qu'il faut écrire, mais bien
    Et tu as commis la même erreur dans l'implémentation bool circle::intersect(shape * other)...

    Je me doute bien que, de ta part, ce n'est que pure distraction
    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

  13. #13
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,Ce n'est qu'un détail de syntax, mais, comme tu passe other sous la forme d'un pointeur, ce n'est pas
    qu'il faut écrire, mais bien
    Et tu as commis la même erreur dans l'implémentation bool circle::intersect(shape * other)...

    Je me doute bien que, de ta part, ce n'est que pure distraction
    Oh...

    Je m'ai trompé :'(

    Merci pour la correction, que je reporte immédiatement dans mon post. Ensuite, je vais aller me cacher sous la caisse de mes chats.
    [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.

  14. #14
    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 Emmanuel Deloget Voir le message
    <snip>Ensuite, je vais aller me cacher sous la caisse de mes chats.
    C'est ca... va te cacher!!! et ne te montre plus tant qu'on ne t'aura pas appelé (dis-je à mon chien quand il a fait une connerie )
    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. [AJAX] construction d'un tableau -> où est l'erreur?
    Par noobC dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 04/08/2008, 15h36
  2. [MySQL] Peu importe la taille du tableau, SQL est censé tout enregistrer(non pas foreach :D )
    Par Dermiste dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 26/04/2008, 01h47
  3. en quoi l init de mon tableau n 'est pas bonne ?
    Par poulette3000 dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 31/10/2007, 17h29
  4. Réponses: 8
    Dernier message: 19/07/2007, 16h40
  5. afficher juste les colonnes du tableau c'est possible !?
    Par moonia dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 26/07/2006, 08h58

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