Partage
  • Partager sur Facebook
  • Partager sur Twitter

Le problème du langage c++.

Impossibilité de redéfinir un type.

    5 juillet 2021 à 10:00:06

    Salut!

    Je me retrouve dans cette situation-ci :

    -J'instancie des entités de types différents, et j'utilise des fonctions virtuelles qui ont un coût à l'exécution et je me suis rendu compte que le seul moyen de réduire l'appel à des fonctions virtuelles c'est d'utiliser un design Entity/Component/System. (ECS)

    Mais je n'aime pas cela, ça me semble très lourd à implémenter, il y a beaucoup de manières différentes d'implémenter cela et de plus, pour chaque entité il faut ajouter un composant par type de composant ce qui peut être lourd quand il y en a beaucoup ce qui est mon cas et quand un composant peut contenir d'autres composants. (Si j'ai plusieurs types d'entités qui sont Transformable et Drawable) je dois ajouter des composants de type drawable et transformable pour tous ces types d'entités si il y a deux/trois types ça passe encore mais si il y en a 1000 ça devient ingérable (c'est ce qu'il faut faire avec Unity), de plus il faut créer ses composants pour chaque instances. 

    De plus pour chaque système il faut vérifier si l'entité possède bien le (ou les) composant(s) nécessaire avant de les mettre à jour puisqu'il n'y a pas de types.

    J'avais essayé de résoudre ce problème à l'aide du polymorphisme statique pour virer les appels aux fonctions virtuelles et utiliser un template variadique pour tout les types avec un ID pour la position du type dans le parameter pack et un vector pour chaque type mais je me retrouve avec le problème des parameter pack c'est à dire :

    -Il faut passer tout les types au parameter pack, si il y en a quelque un, ça passe, mais si il y en a 1000, ça devient ingérable.

    Ce que j'avais pensé faire c'est utiliser une classe qui génère elle même les types en compilation à passer au parameter pack, puisque de toute façon, à la compilation finale (lors de la génération de l'exécutable), je connais tout les types vu qu'il n'est pas possible de créer une nouvelle classe à l'exécution.

    Mais ce n'est pas possible de faire ça en c++, par exemple, ce code ne compile pas :

    template <typename T, typename Tuple>
            struct has_type;
    
            template <typename T>
            struct has_type<T, std::tuple<>> : std::false_type {};
    
            template <typename T, typename U, typename... Ts>
            struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
    
            template <typename T, typename... Ts>
            struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
    
            struct holder {
                auto tp;
                template <typename H, class = typename std::enable_if<has_type<H, decltype(tp)>::value>::type>
                void add (H head) {
                    std::get<std::vector<H>>(tp).push_back(head);
                }
                template <typename H, class..., class = typename std::enable_if<!has_type<H, decltype(tp)>::value>::type>
                void add (H head) {
                    tp = std::tuple_cat(tp, std::make_tuple(std::vector<H>()));
                }
            };
            struct cat {
            };
            struct dog {
            };
            struct bird {
            };
    int main(int argc, char* argv[])
    {
        cat c;
        dog d;
        bird b;
        holder h;
        h.add(c);
        h.add(d);
        h.add(b);
    }

    Parce que le mot clé auto implique que la variable membre soit statique et constante.

    Le langage Linotte (pour ceux qui connaissent) permet d'attacher une nouvelle variable membre à une instance. 

    Mais ce n'est pas possible de faire cela en c++.

    -
    Edité par OmbreNoire 5 juillet 2021 à 10:03:08

    • Partager sur Facebook
    • Partager sur Twitter
      5 juillet 2021 à 10:43:17

      Hello

      J'ai vraiment du mal a comprendre ce que tu cherche a montrer ici...

      Que le code que tu montre ne compile pas? Oui et?
      Que le C++ ne permet pas de faire une certaine chose? Dans ce cas il serait judicieux de mieux définir ce que tu cherches a obtenir. La mentalité j'ai essaye ça ne compile pas donc ce n'est pas possible me chiffonne un peu.

      Par exemple a partir de ton code, j'ai pu faire ceci https://godbolt.org/z/YjdeMdcaG mais vu que je comprends mal ce que tu cherches a obtenir, impossible de savoir si c'est ce que tu veux ou non...
      • Partager sur Facebook
      • Partager sur Twitter
        5 juillet 2021 à 11:35:20

        Salut, ce que je cherche à faire c'est quelque chose comme ceci :

        struct animal {
                unsigned int id;
                unsigned int typeId;
                static unsigned int nbInstances;
                animal(unsigned int typeId) {
                    id = nbInstances;
                    nbInstances = id;
                    nbInstances++;
                    this->typeId = typeId;
                }
                template <typename D>
                void applySpecificBehaviour() {
                  std::cout<<"base beheviour of instance : "<<id<<std::endl;
                  onSepecifiedBehaviourCalled<D>();
                }
                template <typename D>
                void onSepecifiedBehaviourCalled() {
                    static_cast<D&>(*this).onSepecifiedBehaviourCalled();
                }
            };
            unsigned int animal::nbInstances = 0;
            struct cat : animal
            {
              cat() : animal(0) {}
              void applySpecificBehaviour() {
                  animal::applySpecificBehaviour<cat>();
                  std::cout<<"cat beheviour of instance : "<<id<<std::endl;
              }
              void onSepecifiedBehaviourCalled() {
                  std::cout<<"cat on specified behaviour : "<<id<<std::endl;
              }
            };
        
            struct dog : animal
            {
              dog() : animal(1) {}
              void applySpecificBehaviour() {
                  animal::applySpecificBehaviour<dog>();
                  std::cout<<"dog beheviour of instance : "<<id<<std::endl;
              }
              void onSepecifiedBehaviourCalled() {
                  std::cout<<"dog on specified behaviour : "<<id<<std::endl;
              }
            };
        
            struct bird : animal
            {
              bird() : animal(2) {}
              void applySpecificBehaviour() {
                  animal::applySpecificBehaviour<bird>();
                  std::cout<<"bird beheviour of instance : "<<id<<std::endl;
              }
              void onSepecifiedBehaviourCalled() {
                  std::cout<<"bird on specified behaviour : "<<id<<std::endl;
              }
            };
            template <class B, size_t I, class... Derived>
            struct Holder {
        
            };
            template <class B, size_t I, class Head, class... Tail>
            struct Holder<B, I, Head, Tail...> : Holder<B, I+1, Tail...> {
                std::vector<B*> entities;
                void add(B* entity) {
                    if (entity->typeId == I)
                        entities.push_back(entity);
                    Holder<B, I+1, Tail...>::add(entity);
                }
                void applyBehaviours() {
                    for (unsigned int i = 0; i < entities.size(); i++) {
                        static_cast<Head*>(entities[i])->applySpecificBehaviour();
                    }
                    Holder<B, I+1, Tail...>::applyBehaviours();
                }
            };
            template <class B, size_t I, class Head>
            struct Holder<B, I, Head> {
                std::vector<B*> entities;
                void add(B* entity) {
                    if (entity->typeId == I)
                        entities.push_back(entity);
                }
                void applyBehaviours() {
                    for (unsigned int i = 0; i < entities.size(); i++) {
                        static_cast<Head*>(entities[i])->applySpecificBehaviour();
                    }
                }
            };
        int main(int argc, char* argv[])
        {
            cat c1;
            dog d1;
            bird b1;
            cat c2;
            dog d2;
            bird b2;
            Holder<animal, 0, cat, dog, bird> holder;
            holder.add(&c1);
            holder.add(&d1);
            holder.add(&b1);
            holder.add(&c2);
            holder.add(&d2);
            holder.add(&b2);
            holder.applyBehaviours();
            return 0;
        }

        Mais le problème ici c'est qu'il faut passer tout les types au holder, si il y en a quelques uns, ça va, mais si il y en a beaucoup, c'est lourd!!!

        J'aimerai avoir une autre classe qui les génères suivant le type de l'objet que j'ajoute avec la méthode add.

        -
        Edité par OmbreNoire 5 juillet 2021 à 11:35:46

        • Partager sur Facebook
        • Partager sur Twitter
          5 juillet 2021 à 11:48:28

          Si je peux me permettre, c'est pas un problème du langage C++, c'est un problème de méthodologie que tu as.

          Je lis tes topics depuis un moment, j'y réponds de moins en moins parce que tu fais n'importe quoi, et tu ne te remets jamais en question.

          Quand on conceptualise correctement un projet, on ne fait pas du code non-maintenable et épouvantablement compliqué pour rien comme tu fais.

          Je ne réponds plus à tes messages, mais lire que c'est le langage C++ qui a un problème quand on voit ce que tu fais, franchement ça fait râler. 

          Pas la peine de me répondre, et je ne suis même pas sur de re-répondre, de toute façon tout conseil que les gens te donnent, tu les ignores.

          • Partager sur Facebook
          • Partager sur Twitter

          Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

            5 juillet 2021 à 12:05:35

            Le langage a un sérieux problème surtout pour appeler des fonctions virtuelles à l'exécution hors que l'on connait tout les types en compilation.
            • Partager sur Facebook
            • Partager sur Twitter
              5 juillet 2021 à 12:19:32

              Si tu veux dynamiquement créer des classes et des méthodes lors de l'exécution, tu t'es trompé de langage. 

              Penche toi vers un langage interpreté si tu veux faire cela, ou l'exécution du code peut générer un nouveau code. (mais sache que très très tôt dans l'ère de l'informatique, on a vite séparé la partie code de la partie données car on se rendait compte que ça créait des complications phénoménales pour finalement pas trop de raisons valables).

              Mais tu as un sacré soucis de méthodologie. J'espère qu'à un moment tu corrigeras ça. 

              • Partager sur Facebook
              • Partager sur Twitter

              Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                5 juillet 2021 à 12:20:43

                > ce que je cherche à faire c'est quelque chose comme ceci : [...] Mais le problème ici c'est qu'il faut passer tout les types au holder, si il y en a quelques uns, ça va, mais si il y en a beaucoup, c'est lourd!!!

                C'est toi qui a choisi de faire ça, et tu constates toi-même que l'idée est mauvaise. C'est pas la faute au langage (à qui on peut reprocher bien des choses par ailleurs).

                Et si c'est la faute au langage, apprends-en un autre.

                @fvritman très très tôt dans l'ère de l'informatique, on a vite séparé la partie code de la partie données car on se rendait compte que ça créait des complications phénoménales pour finalement pas trop de raisons valables

                Affirmation discutable, très tôt dans l'informatique, LISP (1958) a montré qu'il était intéressant de pouvoir manipuler du code comme des données.

                https://fr.wikipedia.org/wiki/Homoiconicit%C3%A9

                -
                Edité par michelbillaud 5 juillet 2021 à 12:28:09

                • Partager sur Facebook
                • Partager sur Twitter
                  5 juillet 2021 à 12:49:29

                  Ce code n'a absolument aucun sens en plus d'être comme à chacun de tes topics, ultra compliqué. Je t'invite fortement à lire certains projets opensource pour t'inspirer de choses plus simples.

                  Tu parle d'un système à entité et au final tu fais le gros classique du polymorphisme. Le but d'un ECS c'est justement d'éviter du polymorphisme et de l'héritage. Ce qui évite de faire des classes Oiseau, Humain, Dragon et ensuite une dernière classe OiseauHumainDragon qui hérite des trois précédentes.

                  Les templates sont aussi faites pour créer du code orthogonal « qui marche pour tout type distinct » pas pour savoir si une classe a une caractéristique. Certains le font et c'est ce qu'on appelait du SFINAE mais on évite autant que possible sauf cas de force majeur. Encore une fois dans ton cas c'est totalement useless. En plus on a les concepts maintenant.

                  -
                  Edité par markand 5 juillet 2021 à 12:49:37

                  • Partager sur Facebook
                  • Partager sur Twitter

                  git is great because Linus did it, mercurial is better because he didn't.

                    5 juillet 2021 à 16:29:01

                    Bon finalement j'ai réussi à faire ce que je voulais faire!

                    Là, je n'ai plus besoin de passer les types au holder donc je m'en fou si il y en a 1000 mais bon le chaînage de l'appel à la fonction add et le mot clé auto, ça va être compliqué d'implémenter cela dans une classe si je veux récupérer que les entités de la scène qui sont visible et aussi d'utiliser une boucle si je veux ajouter les entités au fur et à mesure.

                    C'est ça le problème du c++, pourtant cette solution est bien plus performante que les fonctions virtuelles et elle permet d'utiliser les avantages de l'héritage et la réutilisation données ou comportements similaire que l'on ne peux pas faire avec un système ECS.

                    Non personnellement j'aime bien cette solution.

                    template <typename T, typename Tuple>
                    struct has_type;
                    
                    template <typename T>
                    struct has_type<T, std::tuple<>> : std::false_type {};
                    
                    template <typename T, typename U, typename... Ts>
                    struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
                    
                    template <typename T, typename... Ts>
                    struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
                    template <class B, size_t I, class... Derived>
                    struct Holder {
                    
                    };
                    template <class B, size_t I, class Head, class... Tail>
                    struct Holder<B, I, Head, Tail...> : Holder<B, I+1, Tail...> {
                        std::vector<B*> entities;
                        void add(B* entity, size_t N) {
                            if (I == N)
                                entities.push_back(entity);
                            Holder<B, I+1, Tail...>::add(entity, N);
                        }
                        void applyBehaviours() {
                            for (unsigned int i = 0; i < entities.size(); i++) {
                                static_cast<Head>(entities[i])->applySpecificBehaviour();
                            }
                            Holder<B, I+1, Tail...>::applyBehaviours();
                        }
                        void copy(Holder<B, I, Tail...>& holder) {
                            Holder<B, I+1, Tail...>::entities = holder.entities;
                            Holder<B, I+1, Tail...>::copy(holder);
                        }
                    };
                    template <class B, size_t I, class Head>
                    struct Holder<B, I, Head> : Holder<B, I+1> {
                        std::vector<B*> entities;
                        void add(B* entity, size_t N) {
                            if (I == N)
                                entities.push_back(entity);
                        }
                        void applyBehaviours() {
                            for (unsigned int i = 0; i < entities.size(); i++) {
                                static_cast<Head>(entities[i])->applySpecificBehaviour();
                            }
                        }
                        void copy(Holder<B, I>& holder) {
                    
                        }
                        void copy(Holder<B, I, Head>& holder) {
                    
                        }
                    };
                    template <class B, size_t I>
                    struct Holder<B, I> {
                        void copy(Holder<B, I>& holder) {
                    
                        }
                    };
                    template <class T, class Tuple>
                    struct Index;
                    
                    template <class T, class... Types>
                    struct Index<T, std::tuple<T, Types...>> {
                        static constexpr std::size_t value = 0;
                    };
                    
                    template <class T, class U, class... Types>
                    struct Index<T, std::tuple<U, Types...>> {
                        static constexpr std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
                    };
                    template <typename B, typename... TupleTypes>
                    struct Types {
                        std::tuple<TupleTypes...> types;
                        Holder<B, 0, TupleTypes...> contents;
                    
                        template <typename H, class = typename std::enable_if_t<has_type<H, decltype(types)>::value>>
                        Types add (H&& head) {
                            contents.add(head, Index<H, decltype(types)>::value);
                            return *this;
                        }
                    
                        template <typename H, class = typename std::enable_if<!has_type<H, decltype(types)>::value>::type>
                        Types<B, H, TupleTypes...> add (H&& head) {
                            Types<B, H, TupleTypes...> types;
                            types.types = std::tuple_cat(std::make_tuple(std::forward<H>(head)), this->types);
                            types.contents.copy(contents);
                            return types.add(std::forward<H>(head));
                        }
                        void applyBehaviours() {
                            contents.applyBehaviours();
                        }
                    };
                    
                    int main(int argc, char* argv[])
                    {
                        cat c1;
                        dog d1;
                        bird b1;
                        cat c2;
                        dog d2;
                        bird b2;
                        Types<animal> types;
                        auto holder = types.add(&c1).add(&d1).add(&b1).add(&c2).add(&d2).add(&b2);
                        holder.applyBehaviours();
                        return 0;
                    }

                    Ca permet de gagner en performances et en maintenabilité du code je trouve.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 juillet 2021 à 17:06:09

                      Si tu ne lis pas ce qu'on te dit et ne te remet jamais en question je t'invite à ne plus poster sur ce forum pour notre bien.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      git is great because Linus did it, mercurial is better because he didn't.

                        5 juillet 2021 à 17:22:06

                        Perso je ne comprends pas pourquoi tu veux essayer de stocker tous les types possibles et imaginables sous une même collection. C'est quoi le problème d'avoir une collection par type? Si je comprends bien ton projet consiste en un moteur de jeu. Si c'est bien ça tu dois savoir exactement quels types de données tu as besoin pour afficher ton model 3D sur l'écran. Pareil pour le son, tu dois savoir exactement de quel type représentera le concept de son, même l'extension du son change, la manière de jouer le son reste le même. Idem pour le moteur physique: tu dois savoir exactement quel type représente la position/rotation/... dans l'espace de ton objet. Au final tu auras certes un nombre important de types différents, mais ce nombre de type sera fini.

                        Tu crois qu'ils font comment chez Qt avec leurs 10000 classes?

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Eug

                          5 juillet 2021 à 19:56:06

                          Si c'est pour recoder un ECS comme le moteur de jeux Unity, je ne vois pas l'intérêt de faire un moteur de jeux, mais pour le polymorphisme statique, besoin de stocker tout les types, le c++ ne fourni aucun moyen de récupérer un type masqué en compilation sans utiliser de paramètres template. (hors on ne peut pas stocker des types différents dans un conteneur sans devoir utiliser un variant ou quelque chose du genre mais je pense pas que ça soit ce qui a de plus performant ça fonctionne un peu comme les fonctions virtuelles je crois)

                          En parlant de ECS je pensais en faire un mais plus évolué, du genre, en créant un conteneur par type de composant/d'entités et par type de systèmes et en le passant a plusieurs fonctions dans le coordinateurs et faire un genre à ceci :

                          int main(int argc, char* argv[]) {
                              EntityManagerArray ema;
                              auto em = ema.add(entity1).add(entity2).add(entity3);
                              ComponentManagerArray cma;
                              auto cm = cm.add(cm1).add(cm2).add(cm3);
                              EntitySystemArray esa;
                              auto es = esa.add(es1).add(es2).add(es3);
                              Coordinator c(); 
                              return c.exec(em, cm, es);
                          }

                          Comme ça si une entité, un composant ou un système, doit hériter des propriétés ou comportements d'un autre, je ne dois pas utiliser de fonctions virtuelles, ni dupliquer les propriétés ou les comportements avec une méthode clone ou je ne sais quoi d'autre.

                          J'ai trouvé un site qui parle justement d'un système ECS et il utilise une fonction virtuelle et une interface IComponentArray avec un système complexe pour mapper les ids des entités avec ceux des composants et une signature pour vérifier que les entités possèdent bien les types de composants requis pour pouvoir itérer sur les entités, bref, je n'ai strictement rien compris :

                          Je n'ai pas encore fait la fonction destroy par contre pour retiré une entité et un type qui n'est plus utilisé.

                          https://austinmorlan.com/posts/entity_component_system/

                          Bref pour bénéficier de bonnes performances et de maintenabilité au niveau du code c'est relativement compliqué.

                          -
                          Edité par OmbreNoire 5 juillet 2021 à 20:02:01

                          • Partager sur Facebook
                          • Partager sur Twitter
                            5 juillet 2021 à 22:12:09

                            OmbreNoire a écrit:

                            le c++ ne fourni aucun moyen de récupérer un type masqué en compilation sans utiliser de paramètres template.

                            Si, il peut (et avec ça aussi) mais c'est pas spécialement recommandé.

                            -
                            Edité par markand 5 juillet 2021 à 22:13:26

                            • Partager sur Facebook
                            • Partager sur Twitter

                            git is great because Linus did it, mercurial is better because he didn't.

                              5 juillet 2021 à 22:46:29

                              Ce qui aurait été bien c'est de pouvoir stocker le typeID de la variable, dans la classe Entity mais on ne peut pas le faire sans utiliser de paramètre template parce que on ne peut utiliser que des variables membres static constexpr size_t et donc elles doivent être initialisée au moment de la définition de la classe car on ne peut pas redéfinir un type en c++ parce que un type doit être constant en compilation, on ne peut pas le changer.

                              • Partager sur Facebook
                              • Partager sur Twitter
                                6 juillet 2021 à 0:13:04

                                >le typeID de la variable

                                Et le RTTI, ou tout autre implémentation du même ordre (et il y en a un paquet), c'est du poulet.

                                Putain, @OmbreNoire, tu fais chier à dire autant de conneries.

                                D'après toi, l'interpréteur de ton langage "fétiche", il est écrit en quoi ? Bordel.

                                C'est pas parce que t'es pas débrouillard que les autres ne le sont pas. Et la plus belle fille du monde n'a qu'elle a offrir, et c'est déjà pas mal.

                                Tant que tu t'obstines à faire des jugements à l'emporte-pièce et que tu ne cherches pas à comprendre nos conseils (et des fois, on a l'impression que c'est fait exprès) t'avanceras pas.

                                On peut tout faire avec n'importe quel langage, c'est juste plus ou moins facile.

                                Sans objectifs précis, chiffrés, tu erreras comme un poulet décapité.

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                  6 juillet 2021 à 8:37:26

                                  OmbreNoire a écrit:

                                  Ce qui aurait été bien c'est de pouvoir stocker le typeID de la variable, dans la classe Entity mais on ne peut pas le faire sans utiliser de paramètre template parce que on ne peut utiliser que des variables membres static constexpr size_t et donc elles doivent être initialisée au moment de la définition de la classe car on ne peut pas redéfinir un type en c++ parce que un type doit être constant en compilation, on ne peut pas le changer.


                                  Il y a des moments où je te lis et j'ai l'impression de lire une page manuel de git tellement ça ne veut rien dire.
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  git is great because Linus did it, mercurial is better because he didn't.

                                    6 juillet 2021 à 9:36:33

                                    Salut, RTTI ne permet pas de récupérer le type du pointeur en compilation, seulement à l'exécution.

                                    Imagions ce cas-ci :

                                    Je possède une classe transformable qui déplace des entités, remet à jour la transformation et appelle une méthode onMove définie dans une classe entity qui hérite de transformable, parce que je dois supposons remettre à jour des données comme la physique ou autre.

                                    Cette même classe entity possède des entités enfants car on peut ça pourrait être une animation par exemple, ou un personnage contenant plusieurs animations.

                                    J'ai trois classes (sphere, rectangle, convexshape) qui héritent de la classe entity.

                                    template <typename T, typename Tuple>
                                    struct has_type;
                                    
                                    template <typename T>
                                    struct has_type<T, std::tuple<>> : std::false_type {};
                                    
                                    template <typename T, typename U, typename... Ts>
                                    struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
                                    
                                    template <typename T, typename... Ts>
                                    struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
                                    template <class B, size_t I, class... Derived>
                                    struct Holder {
                                    
                                    };
                                    template <class B, size_t I, class Head, class... Tail>
                                    struct Holder<B, I, Head, Tail...> : Holder<B, I+1, Tail...> {
                                        std::vector<B*> entities;
                                        void add(B* entity, size_t N) {
                                            if (I == N)
                                                entities.push_back(entity);
                                            Holder<B, I+1, Tail...>::add(entity, N);
                                        }
                                        void move() {
                                            for (unsigned int i = 0; i < entities.size(); i++) {
                                                entities[i].move<Head>();
                                            }
                                            Holder<B, I+1, Tail...>::applyBehaviours();
                                        }
                                        void copy(Holder<B, I, Tail...>& holder) {
                                            Holder<B, I+1, Tail...>::entities = holder.entities;
                                            Holder<B, I+1, Tail...>::copy(holder);
                                        }
                                    };
                                    template <class B, size_t I, class Head>
                                    struct Holder<B, I, Head> : Holder<B, I+1> {
                                        std::vector<B*> entities;
                                        void add(B* entity, size_t N) {
                                            if (I == N)
                                                entities.push_back(entity);
                                        }
                                        void move() {
                                            for (unsigned int i = 0; i < entities.size(); i++) {
                                                entities[i]->move<Head>();
                                            }
                                        }
                                        void copy(Holder<B, I>& holder) {
                                    
                                        }
                                        void copy(Holder<B, I, Head>& holder) {
                                    
                                        }
                                    };
                                    template <class B, size_t I>
                                    struct Holder<B, I> {
                                        void copy(Holder<B, I>& holder) {
                                    
                                        }
                                        void applyBehaviours() {
                                    
                                        }
                                    };
                                    template <class T, class Tuple>
                                    struct Index;
                                    
                                    template <class T, class... Types>
                                    struct Index<T, std::tuple<T, Types...>> {
                                        static constexpr std::size_t value = 0;
                                    };
                                    
                                    template <class T, class U, class... Types>
                                    struct Index<T, std::tuple<U, Types...>> {
                                        static constexpr std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
                                    };
                                    template <typename B, typename... TupleTypes>
                                    struct EntityManager {
                                        std::tuple<TupleTypes...> types;
                                        Holder<B, 0, TupleTypes...> contents;
                                    
                                        template <typename H, class = typename std::enable_if_t<has_type<H, decltype(types)>::value>>
                                        EntityManager add (H&& head) {
                                            contents.add(head, Index<H, decltype(types)>::value);
                                            return *this;
                                        }
                                    
                                        template <typename H, class = typename std::enable_if<!has_type<H, decltype(types)>::value>::type>
                                        EntityManager<B, H, TupleTypes...> add (H&& head) {
                                            EntityManager<B, H, TupleTypes...> entityManager;
                                            types.types = std::tuple_cat(std::make_tuple(std::forward<H>(head)), this->types);
                                            types.contents.copy(contents);
                                            return types.add(std::forward<H>(head));
                                        }
                                        void move() {
                                            contents.move();
                                        }
                                    };
                                    struct Transformable {
                                        template<typename D>
                                        void move() {
                                            static_cast<D>(*this).onMove();
                                        }
                                    };
                                    struct entity {
                                            std::vector<entity*> children;
                                            
                                            template<typename D>
                                            void move() {
                                              std::cout<<"move entity of instance : "<<id<<std::endl;
                                              Transformable::move<D>();
                                              for (unsigned int i = 0; i < children[i].size(); i++) {
                                                  static_cast<???>(children[i]).onMove();
                                              }
                                            }        
                                        };
                                        struct sphere : entity
                                        {
                                          void onMove() {
                                              std::cout<<"update datas on sphere instance : "<<id<<"moved"<<std::endl;
                                          }
                                        };
                                    
                                        struct rectangle : entity
                                        {
                                          void onMove() {
                                              std::cout<<"update datas on rectangle instance : "<<id<<"moved"<<std::endl;
                                          }
                                        };
                                    
                                        struct convexshape : entity
                                        {
                                          void onMove() {
                                              std::cout<<"update data on convex shape : "<<id<<"shape"<<std::endl;
                                          }
                                        };

                                    Il y a un problème, on ne connaît pas le type des entités enfants dans la classe Entity, pour résoudre le problème.

                                    Il y a deux solutions pour régler ce problème :

                                    -On pourrait utiliser une fonction virtuelle mais ça a un surcoût à l'exécution et si l'entité possède beaucoup d'entités enfants comme une animation par exemple  et qu'on la déplace souvent ce qui est le cas dans un jeux, c'est contre performant.

                                    -On pourrait utiliser un système ECS mais dans ce cas là ça serait compliqué à gérer d'ailleurs je ne vois pas du tout comment faire. (Unity le fait mais je pense qu'il utilise un laguage interprété (le C#) donc c'est peut être plus simple à faire dans ce cas là)

                                    On ne peut pas déclarer un EntityManager dans la classe Entity, car, les types des entités enfants peuvent être de n'importe quel type (si le personnage possède une arme par exemple ou des équipements.)

                                    Il faudrait donc pouvoir faire quelque chose comme ceci :

                                    struct entity {
                                            auto children;
                                            void addChild(Entity* entity) {
                                                children = children.add(entity);
                                            }
                                            template<typename D>
                                            void move() {
                                              std::cout<<"move entity of instance : "<<id<<std::endl;
                                              Transformable::move<D>();
                                              children.move();
                                            }       
                                        };

                                    Rendre la classe Entity template poserait problème car le type du template ne peut pas changer dans la classe Entity.

                                    De ce fait on est obligé d'utiliser une fonction template et de faire quelque chose comme ceci :

                                    template <typename T, typename Tuple>
                                    struct has_type;
                                    
                                    template <typename T>
                                    struct has_type<T, std::tuple<>> : std::false_type {};
                                    
                                    template <typename T, typename U, typename... Ts>
                                    struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
                                    
                                    template <typename T, typename... Ts>
                                    struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
                                    template <class B, size_t I, class... Derived>
                                    struct Holder {
                                    
                                    };
                                    template <class B, size_t I, class Head, class... Tail>
                                    struct Holder<B, I, Head, Tail...> : Holder<B, I+1, Tail...> {
                                        std::vector<B*> entities;
                                        void add(B* entity, size_t N) {
                                            if (I == N)
                                                entities.push_back(entity);
                                            Holder<B, I+1, Tail...>::add(entity, N);
                                        }
                                        void move() {
                                            for (unsigned int i = 0; i < entities.size(); i++) {
                                                entities[i].move<Head>();
                                            }
                                            Holder<B, I+1, Tail...>::applyBehaviours();
                                        }
                                        void copy(Holder<B, I, Tail...>& holder) {
                                            Holder<B, I+1, Tail...>::entities = holder.entities;
                                            Holder<B, I+1, Tail...>::copy(holder);
                                        }
                                    };
                                    template <class B, size_t I, class Head>
                                    struct Holder<B, I, Head> : Holder<B, I+1> {
                                        std::vector<B*> entities;
                                        void add(B* entity, size_t N) {
                                            if (I == N)
                                                entities.push_back(entity);
                                        }
                                        void move() {
                                            for (unsigned int i = 0; i < entities.size(); i++) {
                                                entities[i]->move<Head>();
                                            }
                                        }
                                        void copy(Holder<B, I>& holder) {
                                    
                                        }
                                        void copy(Holder<B, I, Head>& holder) {
                                    
                                        }
                                    };
                                    template <class B, size_t I>
                                    struct Holder<B, I> {
                                        void copy(Holder<B, I>& holder) {
                                    
                                        }
                                        void applyBehaviours() {
                                    
                                        }
                                    };
                                    template <class T, class Tuple>
                                    struct Index;
                                    
                                    template <class T, class... Types>
                                    struct Index<T, std::tuple<T, Types...>> {
                                        static constexpr std::size_t value = 0;
                                    };
                                    
                                    template <class T, class U, class... Types>
                                    struct Index<T, std::tuple<U, Types...>> {
                                        static constexpr std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
                                    };
                                    template <typename B, typename... TupleTypes>
                                    struct EntityManager {
                                        std::tuple<TupleTypes...> types;
                                        Holder<B, 0, TupleTypes...> contents;
                                    
                                        template <typename H, class = typename std::enable_if_t<has_type<H, decltype(types)>::value>>
                                        EntityManager add (H&& head) {
                                            contents.add(head, Index<H, decltype(types)>::value);
                                            return *this;
                                        }
                                    
                                        template <typename H, class = typename std::enable_if<!has_type<H, decltype(types)>::value>::type>
                                        EntityManager<B, H, TupleTypes...> add (H&& head) {
                                            EntityManager<B, H, TupleTypes...> entityManager;
                                            types.types = std::tuple_cat(std::make_tuple(std::forward<H>(head)), this->types);
                                            types.contents.copy(contents);
                                            return types.add(std::forward<H>(head));
                                        }
                                        void move() {
                                            contents.move();
                                        }
                                    };
                                    struct Transformable {
                                        template<typename D>
                                        void move() {
                                            static_cast<D>(*this).onMove();
                                        }
                                    };
                                    struct entity {
                                            template<typename EntityManager>
                                            auto& addChild(EntityManager& entityManager, Entity* entity) {
                                                return entityManager.add(entity);
                                            }
                                            template<typename D, typename EntityManager>
                                            void move(EntityManager& entityManager) {
                                              std::cout<<"move entity of instance : "<<id<<std::endl;
                                              Transformable::move<D>();
                                              entityManager.move();
                                            }        
                                        };
                                        struct sphere : entity
                                        {
                                          void onMove() {
                                              std::cout<<"update datas on sphere instance : "<<id<<"moved"<<std::endl;
                                          }
                                        };
                                    
                                        struct rectangle : entity
                                        {
                                          void onMove() {
                                              std::cout<<"update datas on rectangle instance : "<<id<<"moved"<<std::endl;
                                          }
                                        };
                                    
                                        struct convexshape : entity
                                        {
                                          void onMove() {
                                              std::cout<<"update data on convex shape : "<<id<<"shape"<<std::endl;
                                          }
                                        };

                                    Ce qui est lourd, pour que ça soit performant il faut créer un contenaire EntityManagerArray qui contient tout les EntityManager de toutes les entités enfants pour chaque entité histoire de ne pas avoir à parcourir toutes les entités pour rechercher les entités enfants et les déplacer ce qui serait contre performant.

                                    Hors que le compilateur pourrait redéduire le type de l'entity manager contenant les entités enfants.

                                    Maintenant oui, en c++ on peut tout faire, mais, la manière de le faire est parfois bien compliquée.

                                    Mais bon avec ce système, je bénéficie des avantages qu'offre l'héritage et un système ECS, en retirant les inconvénients. Le seul bémol est l'utilisation de la mémoire qui augmente un peu car ça occupe plus de place de créer un std::vector par type, plutôt qu'un std::vector pour tout les types à cause de la position du première élément pour chaque std::vector, mais bon, avec la taille des RAM de maintenant ça devrait passer.



                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      6 juillet 2021 à 9:48:44

                                      Unity n'utilise pas de langage interprêté comme le C# pour son moteur.
                                      unity est codé en C++, en revanche, oui il utilise le C# (tout comme le javascript) comme langage de script mis a disposition a de l'utilisateur.

                                      Edit : au temps pour moi, il utilise les deux, du C# et du C++ a priori.

                                      -
                                      Edité par ironwolf151 6 juillet 2021 à 9:51:49

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        6 juillet 2021 à 11:49:43

                                        Bon, j'ai essayé ça mais ça ne compile pas :

                                        template <typename T, typename Tuple>
                                        struct has_type;
                                        
                                        template <typename T>
                                        struct has_type<T, std::tuple<>> : std::false_type {};
                                        
                                        template <typename T, typename U, typename... Ts>
                                        struct has_type<T, std::tuple<U, Ts...>> : has_type<T, std::tuple<Ts...>> {};
                                        
                                        template <typename T, typename... Ts>
                                        struct has_type<T, std::tuple<T, Ts...>> : std::true_type {};
                                        template <class B, size_t I, class... Derived>
                                        struct Holder {
                                        
                                        };
                                        template <class B, size_t I, class Head, class... Tail>
                                        struct Holder<B, I, Head, Tail...> : Holder<B, I+1, Tail...> {
                                            std::vector<B*> entities;
                                            void add(B* entity, size_t N) {
                                                if (I == N)
                                                    entities.push_back(entity);
                                                Holder<B, I+1, Tail...>::add(entity, N);
                                            }
                                            void move() {
                                                for (unsigned int i = 0; i < entities.size(); i++) {
                                                    Head h;
                                                    entities[i]->move(h);
                                                }
                                                Holder<B, I+1, Tail...>::move();
                                            }
                                            void copy(Holder<B, I, Tail...>& holder) {
                                                Holder<B, I+1, Tail...>::entities = holder.entities;
                                                Holder<B, I+1, Tail...>::copy(holder);
                                            }
                                        };
                                        template <class B, size_t I, class Head>
                                        struct Holder<B, I, Head> : Holder<B, I+1> {
                                            std::vector<B*> entities;
                                            void add(B* entity, size_t N) {
                                                if (I == N)
                                                    entities.push_back(entity);
                                            }
                                            void move() {
                                                for (unsigned int i = 0; i < entities.size(); i++) {
                                                    Head h;
                                                    entities[i]->move(h);
                                                }
                                            }
                                            void copy(Holder<B, I>& holder) {
                                        
                                            }
                                            void copy(Holder<B, I, Head>& holder) {
                                        
                                            }
                                        };
                                        template <class B, size_t I>
                                        struct Holder<B, I> {
                                            void copy(Holder<B, I>& holder) {
                                        
                                            }
                                            void applyBehaviours() {
                                        
                                            }
                                            void move() {
                                            }
                                        };
                                        template <class T, class Tuple>
                                        struct Index;
                                        
                                        template <class T, class... Types>
                                        struct Index<T, std::tuple<T, Types...>> {
                                            static constexpr std::size_t value = 0;
                                        };
                                        
                                        template <class T, class U, class... Types>
                                        struct Index<T, std::tuple<U, Types...>> {
                                            static constexpr std::size_t value = 1 + Index<T, std::tuple<Types...>>::value;
                                        };
                                        template <typename B, typename... TupleTypes>
                                        struct EntityManager {
                                            std::tuple<TupleTypes...> types;
                                            Holder<B, 0, TupleTypes...> contents;
                                            std::string name;
                                        
                                            template <typename H, class = typename std::enable_if_t<has_type<H, decltype(types)>::value>>
                                            EntityManager add (H&& head) {
                                                contents.add(head, Index<H, decltype(types)>::value);
                                                return *this;
                                            }
                                        
                                            template <typename H, class = typename std::enable_if<!has_type<H, decltype(types)>::value>::type>
                                            EntityManager<B, H, TupleTypes...> add (H&& head) {
                                                EntityManager<B, H, TupleTypes...> entityManager;
                                                entityManager.types = std::tuple_cat(std::make_tuple(std::forward<H>(head)), this->types);
                                                entityManager.contents.copy(contents);
                                                return entityManager.add(std::forward<H>(head));
                                            }
                                            void move() {
                                                contents.move();
                                            }
                                        };
                                        struct transformable {
                                            template<typename D>
                                            void move() {
                                                static_cast<D&>(*this).onMove();
                                            }
                                        };
                                        struct entity : transformable {
                                                unsigned int id;
                                                static unsigned int nbEntities;
                                                entity() : transformable () {
                                                    id = nbEntities;
                                                    nbEntities++;
                                                }
                                                template <typename D, typename EntityManagerArray>
                                                auto addChild(EntityManagerArray ema, D* entity) {
                                        
                                                    ::EntityManager em = ema.add(entity);
                                                    return em;
                                                }
                                                template<typename D>
                                                void move(D* d) {
                                                  std::cout<<"move entity of instance : "<<id<<std::endl;
                                                  transformable::move<D>();
                                                  //ems.move();
                                                }
                                            };
                                            unsigned int entity::nbEntities = 0;
                                            struct sphere : entity
                                            {
                                              void onMove() {
                                                  std::cout<<"update datas on sphere instance : "<<id<<" moved"<<std::endl;
                                              }
                                            };
                                        
                                            struct rectangle : entity
                                            {
                                              void onMove() {
                                                  std::cout<<"update datas on rectangle instance : "<<id<<" moved"<<std::endl;
                                              }
                                            };
                                        
                                            struct convexshape : entity
                                            {
                                              void onMove() {
                                                  std::cout<<"update data on convex shape : "<<id<<" shape"<<std::endl;
                                              }
                                            };
                                        
                                        int main(int argc, char* argv[])
                                        {
                                        
                                        
                                            sphere sph;
                                            rectangle rect;
                                            convexshape shape, shapeSphereChild;
                                            ::EntityManager<entity> sphereChildren;
                                            sphereChildren.name = "sphere0children";
                                            ::EntityManager sphere0Children = sph.addChild(sphereChildren, &shapeSphereChild);
                                            std::cout<<"name : "<<sphereChildren.name<<std::endl;
                                            ::EntityManager<entity> ems;
                                            ::EntityManager em = ems.add(&sph).add(&rect).add(&shape);
                                            return 0;
                                        }
                                        C:\Users\Laurent\Windows\Demos\ODFAEGCREATOR\main.cpp|647|error: use of deleted function 'EntityManager<entity, convexshape*&>::EntityManager()'|



                                        L'idée est de passer l'entity manager des entités enfants, ajouter l'entité enfant et retourner le nouveau type.

                                        Je ne peux pas utiliser de référence ni de pointer sinon il me dit "auto must be followed by a simple declarator type".

                                        Du coup il râle.

                                        Si quelqu'un à une solution je suis preneur, j'aimerais même pouvoir stocker l'entity manager pour les entités enfants, dans la classe entity, mais je ne pense pas que cela soit possible.

                                        -
                                        Edité par OmbreNoire 6 juillet 2021 à 11:51:05

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          6 juillet 2021 à 12:09:25

                                          J'ai remarqué un schéma

                                          • je veux faire un truc,
                                          • ça marche pas
                                          • c'est la faute au langage C++
                                          • arrêtez de me dire que je m'y prends mal, vous y comprenez rien
                                          • tiens vous voyez ça marche
                                          • je suis un génie
                                          • ah merde non ça marche pas.
                                          • j'aimerai pouvoir mais c'est pas possible.

                                          -
                                          Edité par michelbillaud 6 juillet 2021 à 12:10:13

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            6 juillet 2021 à 12:57:37

                                            Toujours les mêmes conneries avec des jugements à l'emporte-pièce sur des données complètement fausses.

                                            Le poulet est encore vif, vous saviez qu'un poulet a survécu plus d'un an après qu'un fermier l'ait "quasi décapité" (nourrissage à la pipette) ?

                                            https://fr.wikipedia.org/wiki/Mike_le_poulet_sans_t%C3%AAte#:~:text=Des%20articles%20parurent%20dans%20le,dans%20un%20motel%20de%20Phoenix.

                                            N'en mais, depuis quand C# est un langage interprété ? Il se ne nomme comment cet "interpreter" ? "Le fantasme d'OmbreNoire" ? "La Vengeance du Poulet Masqué Décapité" ?

                                            A part l'argument débile de "si c'est pour faire comme les autres, ça vaut pas la peine", pourquoi veux-tu faire cela ?

                                            Donne nous un cas CONCRET d'utilisation de ton machin qui n'est pas avantageusement remplaçable par des mécanismes plus standards ?

                                            Comme tu dis d'énormes conneries pour "invalider" les autres solutions, forcément "T'as raison".

                                            Mais faut un peu se remettre en question de temps en temps.

                                            >parce que je dois supposons remettre à jour des données comme la physique ou autre.

                                            Bin non, il y a plein de moyens plus finauds que de bêtement tout recalculer sur un CPU pas fait pour ça. Tu les mets où les shaders dans ton usine à gaz ?

                                            >Cette même classe entity possède des entités enfants car on peut ça pourrait être une animation par exemple, ou un personnage contenant plusieurs animations.

                                            Mais on sent fout de ces relations enfants parents, dans les faits c'est juste un partage d'une matrice de base. Un simple bidule que les librairies graphiques collent dans un "state" à la con.

                                            >Il y a un problème, on ne connaît pas le type des entités enfants dans la classe Entity,

                                            Et tout ça à la compilation ??? C'est quoi ton univers ? Un endroit où rien ne change, une sphère restera une sphère jusqu'à la fin des temps ? Qu'elle se prenne une planète sur la tronche ou qu'elle est spaguetissée par un trou noir, c'est toujours une "sphère".

                                            Non, "tout" n'est pas faisable ou pertinent à la compilation.

                                            >Il y a deux solutions pour régler ce problème :

                                            Débilité, oups sophisme habituel, "je connais tout sur tout et je peux donc évaluer de manière définitive tout sur tout".

                                            Non, personne ne sait tout, et particulièrement toi, personnification du concept Dunning-Kruger.

                                            C'est pour quand ton séjour dans la "vallée de l'humilité" ?

                                            >On pourrait utiliser une fonction virtuelle mais ça a un surcoût à l'exécution

                                            Peut-être, mais c'est peut-être acceptable, en fonction des contraintes et de la manière dont c'est implémenté et comment ça sera implémenté dans le futur.

                                            Si sur une plateforme actuelle ou dans le futur, ou dans une situation donnée, l'approche "fonction virtuelle" est plus performante, tu fais quoi ? Tu recommences tout ?

                                            Tu générales sans prendre la peine de restreindre les conclusions à tes connaissances actuelles (tu n'as pas, et nous non plus, la science infuse).

                                            >On pourrait utiliser un système ECS mais dans ce cas là ça serait compliqué à gérer d'ailleurs je ne vois pas du tout comment faire

                                            Renseignes-toi, BORDEL. Avant d'asséner tes conclusions débiles.

                                            >Unity le fait mais je pense qu'il utilise un laguage interprété (le C#)

                                            Sans commentaire, tant d'ignorance crasse.

                                            Unity fonctionne sous iOS et Apple interdit l'exécution de bytecode. Tout le code IL de .NET est converti en CPP pour leur faire plaisir (IL2CPP).

                                            Pas mal pour un langage pourri, LOL.

                                            >Il faudrait donc pouvoir faire quelque chose comme ceci :

                                            Non, mais, sérieux, t'as réfléchi 2 minutes avant de sortie une telle énormité ?

                                            Non, c'est vrai, stocker la matrice de transformation pour que les mouvements soient relatifs au nœud parent, c'est trop "old school".

                                            Quelles sont tes connaissances sur "l'état de l'art" des moteurs de jeu ? Parce que, pour faire mieux que les autres, faut au moins savoir ce que font les autres.

                                            Ta solution, de ma fenêtre, c'est une réponse à un faux problème, à une question mal posée, c'est navrant.

                                            P.S.: Comme les compositions des scènes ne doivent pas être dans le code (on recompile pas à chaque ajout/modification/suppression d'asset, et on ne demande pas à un Game Designer de toucher au code) mais dans des fichiers "fait pour", c'est quoi l'intérêt de ce machin au compile time ?

                                            -
                                            Edité par bacelar 6 juillet 2021 à 13:02:43

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                              6 juillet 2021 à 13:01:31

                                              Non en fait ce n'est pas possible sans les fonctions virtuelles ou bien un autre design sans héritage, tout simplement parce que :

                                              -Je ne peux pas rajouter des types d'entités dans un conteneur à l'exécution, là sa compile parce que il connaît le type en compilation :

                                              ::EntityManager em = ems.add(&sph).add(&rect).add(&shape);

                                              Je peux même le faire dans une boucle qui gère des évènements ça fonctionne à partir du moment ou il connaît les tyepes en compilation :

                                              sphere sph;
                                                  rectangle rect;
                                                  convexshape shape;
                                                  RenderWindow rw(sf::VideoMode(800, 600), "test");
                                                  ::EntityManager<entity> ems;
                                                  ::EntityManager em = ems.add(&sph);
                                              
                                                  while (rw.isOpen()) {
                                                      IEvent event;
                                                      while (rw.pollEvent(event)) {
                                                          if (event.type == IEvent::KEYBOARD_EVENT && event.keyboard.type == IEvent::KEY_EVENT_PRESSED && event.keyboard.code == IKeyboard::A) {
                                                              ::EntityManager em2 = em.add(&rect).add(&shape);
                                                              em2.move();
                                                          }
                                                      }
                                                  }

                                              Par contre, dans une fonction autre que la fonction qui la déclare, ça ne fonctionne plus parce que une fonction peut être appelée à  l'exécution et donc dans ce cas là il râle parce que il ne connait pas le type en compilation du coup il met met cette erreur comme quoi le type est mal formé :

                                              template <typename D, typename EntityManagerArray>
                                                      auto addChild(EntityManagerArray ema, D* entity) {
                                                          
                                                          return ema.add(entity);
                                                      }



                                              Je dois donc juste fournir tout les types dans une seule fonction et les passer à toutes les autres fonctions template, en fait c'est moi qui m'y prend mal. :)

                                              -
                                              Edité par OmbreNoire 6 juillet 2021 à 13:05:42

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                6 juillet 2021 à 13:05:33

                                                >en fait c'est moi qui m'y prend mal.

                                                Posez le besoin INITIAL avant de faire une usine à gaz.

                                                C'est quoi votre besoin INITIAL (et pas "je veux pas faire comme les autres" SVP).

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                  6 juillet 2021 à 13:42:11

                                                  bacelar a écrit:

                                                  >en fait c'est moi qui m'y prend mal.

                                                  Posez le besoin INITIAL avant de faire une usine à gaz.

                                                  C'est quoi votre besoin INITIAL (et pas "je veux pas faire comme les autres" SVP).


                                                  Je voudrais modifier le type de mes données à l'exécution et pas en compilation, mais je ne pense pas que c'est possible de faire cela en c++.

                                                  Y a t'il un autre langage qui permet de faire cela ? 

                                                  Si par exemple je veux rajouter un type à un std::tuple mais à l'exécution. 

                                                  le langage linotte possède cette fonctionnalité et le gaz m'a dit ceci :

                                                  Bonjour @Ornito ,
                                                  en effet, j'utilise le principe des prototypes pour attacher des méthodes aux instances des "objets" du langage. ça me permet d'ajouter des fonctionnalités au langage.
                                                  Mais j'ai l'impression que le langage est trop simple pour tes besoins ?



                                                  Mais le langage n'est pas assez poussé au niveau graphisme pour faire ce que je veux faire.

                                                  Et pouvoir faire quelque chose comme ceci :

                                                  dynamic_cast<typeid(*entity)>(entity)->function();



                                                  -
                                                  Edité par OmbreNoire 6 juillet 2021 à 14:18:54

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    6 juillet 2021 à 15:35:35

                                                    OmbreNoire a écrit:

                                                    bacelar a écrit:

                                                    >en fait c'est moi qui m'y prend mal.

                                                    Posez le besoin INITIAL avant de faire une usine à gaz.

                                                    C'est quoi votre besoin INITIAL (et pas "je veux pas faire comme les autres" SVP).


                                                    Je voudrais modifier le type de mes données à l'exécution et pas en compilation, mais je ne pense pas que c'est possible de faire cela en c++.

                                                    Non "je voudrais modifier le type", c'est pas le besoin INITIAL. Je ne vois personne qui paierait 0,10 € pour avoir un programme qui modifie le type des données.   Il faudrait un exemple _précis_ de situation où modifier le type de données (etc) serait _la_ solution à retenir.

                                                    On est visiblement dans une situation typique de problème XY https://fr.wikipedia.org/wiki/Probl%C3%A8me_XY

                                                    Le problème XY est un problème de communication rencontré lors d'une demande d'assistance. La personne ayant un problème X imagine une solution Y, et au lieu de demander de l'aide pour X, cette personne demande de l'aide pour mettre en place la solution Y. Cependant, il arrive que résoudre le problème Y ne résolve que de manière partielle ou bancale le problème X. Ainsi, ne pas présenter le problème original et introduire un problème autre peut conduire à des difficultés de communication et à des solutions insatisfaisantes.

                                                    Ce problème est fréquemment rencontré par les centres et services d'assistance. L'utilisateur ayant déjà tenté de résoudre le problème X pense sa solution Y efficace mais n'arrive pas à la mettre en œuvre. L'incapacité de la structure d'assistance à résoudre le problème de base ou à en comprendre la nature conduit à des frustrations de l'utilisateur. La situation peut être découverte quand l'utilisateur pose des questions à propos de détails sans rapport avec le sujet. La solution pour les personnes chargées de l'assistance est de poser des questions sur ce qui motive la requête afin d'identifier le problème de base et de réorienter l'utilisateur vers la source réelle de ses ennuis.

                                                    Ici c'est encore mieux : l'utilisateur affirme simultanément

                                                    • que Y est la solution à X
                                                    • et que Y est impossible.
                                                    A part ça tout va bien ?

                                                    -
                                                    Edité par michelbillaud 6 juillet 2021 à 15:42:27

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      6 juillet 2021 à 15:40:16

                                                      Bon c'est l'instanciation du std::tuple qui posait problème, je l'ai retiré et maintenant ça compile!!!

                                                      template < typename Tp, typename... List >
                                                      struct contains : std::true_type {};
                                                      
                                                      template < typename Tp, typename Head, typename... Rest >
                                                      struct contains<Tp, Head, Rest...>
                                                      : std::conditional< std::is_same<Tp, Head>::value,
                                                          std::true_type,
                                                          contains<Tp, Rest...>
                                                      >::type {};
                                                      
                                                      template < typename Tp >
                                                      struct contains<Tp> : std::false_type {};
                                                      
                                                      
                                                      template <typename T, typename U=void, typename... Types>
                                                      constexpr size_t index() {
                                                          return std::is_same<T, U>::value ? 0 : 1 + index<T, Types...>();
                                                      }
                                                      template <class B, size_t I, class... Derived>
                                                      struct Holder {
                                                      
                                                      };
                                                      template <class B, size_t I, class Head, class... Tail>
                                                      struct Holder<B, I, Head, Tail...> : Holder<B, I+1, Tail...> {
                                                          std::vector<B*> entities;
                                                          void add(B* entity, size_t N) {
                                                              if (I == N)
                                                                  entities.push_back(entity);
                                                              Holder<B, I+1, Tail...>::add(entity, N);
                                                          }
                                                          void move() {
                                                              for (unsigned int i = 0; i < entities.size(); i++) {
                                                                  Head h;
                                                                  entities[i]->move(h);
                                                              }
                                                              Holder<B, I+1, Tail...>::move();
                                                          }
                                                          void copy(Holder<B, I, Tail...>& holder) {
                                                              Holder<B, I+1, Tail...>::entities = holder.entities;
                                                              Holder<B, I+1, Tail...>::copy(holder);
                                                          }
                                                      };
                                                      template <class B, size_t I, class Head>
                                                      struct Holder<B, I, Head> : Holder<B, I+1> {
                                                          std::vector<B*> entities;
                                                          void add(B* entity, size_t N) {
                                                              if (I == N)
                                                                  entities.push_back(entity);
                                                          }
                                                          void move() {
                                                              for (unsigned int i = 0; i < entities.size(); i++) {
                                                                  Head h;
                                                                  entities[i]->move(h);
                                                              }
                                                          }
                                                          void copy(Holder<B, I>& holder) {
                                                      
                                                          }
                                                          void copy(Holder<B, I, Head>& holder) {
                                                      
                                                          }
                                                      };
                                                      template <class B, size_t I>
                                                      struct Holder<B, I> {
                                                          void copy(Holder<B, I>& holder) {
                                                      
                                                          }
                                                          void applyBehaviours() {
                                                      
                                                          }
                                                          void move() {
                                                          }
                                                      };
                                                      
                                                      template <typename B, typename... TupleTypes>
                                                      struct EntityManager {
                                                          Holder<B, 0, TupleTypes...> contents;
                                                          std::string name;
                                                      
                                                          template <typename H, class = typename std::enable_if_t<contains<H, TupleTypes...>::value>>
                                                          EntityManager add (H&& head) {
                                                              contents.add(head, index<H, TupleTypes...>());
                                                              return *this;
                                                          }
                                                      
                                                          template <typename H, class = typename std::enable_if<!contains<H, TupleTypes...>::value>::type>
                                                          EntityManager<B, H, TupleTypes...> add (H&& head) {
                                                              EntityManager<B, H, TupleTypes...> entityManager;
                                                              entityManager.contents.copy(contents);
                                                              return entityManager.add(std::forward<H>(head));
                                                          }
                                                          void move() {
                                                              contents.move();
                                                          }
                                                      };
                                                      struct transformable {
                                                          template<typename D>
                                                          void move() {
                                                              static_cast<D&>(*this).onMove();
                                                          }
                                                      };
                                                      struct entity : transformable {
                                                              unsigned int id;
                                                              static unsigned int nbEntities;
                                                              entity() : transformable () {
                                                                  id = nbEntities;
                                                                  nbEntities++;
                                                              }
                                                              template <typename D, typename EntityManagerArray>
                                                              auto addChild(EntityManagerArray& ema, D* entity) {
                                                      
                                                                  return ema.add(entity);
                                                              }
                                                              template<typename D>
                                                              void move(D* d) {
                                                                std::cout<<"move entity of instance : "<<id<<std::endl;
                                                                transformable::move<D>();
                                                                //ems.move();
                                                              }
                                                          };
                                                          unsigned int entity::nbEntities = 0;
                                                          struct sphere : entity
                                                          {
                                                            void onMove() {
                                                                std::cout<<"update datas on sphere instance : "<<id<<" moved"<<std::endl;
                                                            }
                                                          };
                                                      
                                                          struct rectangle : entity
                                                          {
                                                            void onMove() {
                                                                std::cout<<"update datas on rectangle instance : "<<id<<" moved"<<std::endl;
                                                            }
                                                          };
                                                      
                                                          struct convexshape : entity
                                                          {
                                                            void onMove() {
                                                                std::cout<<"update data on convex shape : "<<id<<" shape"<<std::endl;
                                                            }
                                                          };
                                                      
                                                      int main(int argc, char* argv[])
                                                      {
                                                      
                                                      
                                                          sphere sph;
                                                          rectangle rect;
                                                          convexshape shape;
                                                          RenderWindow rw(sf::VideoMode(800, 600), "test");
                                                          ::EntityManager<entity> ems;
                                                          ::EntityManager<entity> childrenem;
                                                          ::EntityManager children0em = sph.addChild(childrenem, &shape);
                                                          ::EntityManager em = ems.add(&sph).add(&rect).add(&shape);
                                                          em.move();
                                                          while (rw.isOpen()) {
                                                              IEvent event;
                                                              while (rw.pollEvent(event)) {
                                                                  if (event.type == IEvent::KEYBOARD_EVENT && event.keyboard.type == IEvent::KEY_EVENT_PRESSED && event.keyboard.code == IKeyboard::A) {
                                                                      ::EntityManager em2 = em.add(&rect).add(&shape);
                                                                      em2.move();
                                                                  }
                                                              }
                                                          }
                                                          return 0;
                                                      }



                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        6 juillet 2021 à 17:57:57

                                                        >Je voudrais modifier le type de mes données à l'exécution et pas en compilation

                                                        Non, mais, tu rigoles ???

                                                        C'est quoi un constructeur d'une classe A qui prend une "référence gauche" sur une instance de classe B en paramètre dans la majorité des cas ?

                                                        Bon, @michelbillaud a bien résumé le problème, @OmbreNoire n'a toujours pas compris qu'il se pose un faux problème.

                                                        Quand on fait une scène avec des objets "hiérarchique", on ne modifie pas les coordonnées des enfants car ces coordonnées sont relatifs au référentiel que forme le nœud parent.
                                                        - Pas besoin de ce "move" à la con
                                                        - L'ensemble des changements de référentiel tout le long de l'arbre, ça se gère avec une simple pile de matrice
                                                        - les mécanismes d'optimisation de ce type de graphe sont légions (octree, etc...)
                                                        - ...

                                                        C'est quoi le VRAI besoin, putain !!
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                          6 juillet 2021 à 21:53:47

                                                          En fait je ne sais pas si vous avez remarqué mais on a absolument aucun effet sur YES, man. C'est à dire quoi qu'on dise il continue son roman. Un peu comme un stop pub sur une boite aux lettre de nos jours : inutile.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          git is great because Linus did it, mercurial is better because he didn't.

                                                            6 juillet 2021 à 22:53:57

                                                            markand a écrit:

                                                            En fait je ne sais pas si vous avez remarqué mais on a absolument aucun effet sur YES, man. C'est à dire quoi qu'on dise il continue son roman. Un peu comme un stop pub sur une boite aux lettre de nos jours : inutile.


                                                            Objection, dans mon village, les "stop pubs" sont plutôt bien respectés :)

                                                            Sinon, je partage totalement ton analyse. J'admire le temps et l'énergie (vaine) que met par exemple Bacelar pour lui répondre sur ce topic.

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                                                            Le problème du langage c++.

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