Partage
  • Partager sur Facebook
  • Partager sur Twitter

undefined reference to `fonction`

    18 novembre 2021 à 21:40:39

    Bonsoir à tous !

    Je bosse sur un projet pour ma fac (qui sera en définitive un jeu style platformer en 2D mais c'est pas important), j'utilise une structure de donnée "Entity" pour représenter tout ce qui peut exister dans le jeu. J'ai une fonction allEntities(), qui renvoie un static vector d'Entity, afin de contenir l'ensemble des entités existants. Afin de ne pas surcharger mon vector avec des entités inactives, j'ai une fonction refresh(), qui permet de supprimer une entité si elle n'est plus active.

    Le soucis, c'est que lorsque je compile, il me renvoie cette erreur : 

    obj\Release\Engine\Engine.o:Engine.cpp|| undefined reference to `std::vector<Entity, std::allocator<Entity> >& allEntities<std::vector<Entity, std::allocator<Entity> >&>()'|

    Je ne comprends pas cette erreur, j'ai pourtant bien définie ma fonction allEntities, et mes inclusions sont correctes... Est-ce que vous pouvez m'aider ? Je vous mets ici ma structure Entity, ma fonction allEntities, et ma fonction refresh, même si ces derniers sont assez sommaires :

    /**
     * structure Entity
     */
    
    //EntityID est un using std::size_t
    //Signature est un using std::bitset
    struct Entity {
        Entity();
    
        bool active;
        EntityID id;
        Signature compSignature;
    };
    
    /**
     * fonction allEntities
     */
    
    std::vector<Entity>& allEntities() {
        static std::vector<Entity> entities;
        return entities;
    }
    
    /**
     * fonction refresh
     */
    
    void refresh() {
        auto& entities = allEntities();
        std::vector<Entity>::iterator i = entities.begin();
        while(i != entities.end()) {
            if(!i->active) {
                i = entities.erase(i);
            } else {
                i++;
            }
        }
        /*je faisais ça avant, mais ça me mettait une autre erreur comme quoi la fonction erase du vector<Entity> entities n'était pas définie
    
        auto end = std::remove_if(entities.begin(),entities.end(),[&](Entity const& e) {return !e.active;});
        entities.erase(end,entities.end());
        */
    }




    • Partager sur Facebook
    • Partager sur Twitter
      18 novembre 2021 à 22:24:54

      Bonjour,

      Je ne sais pas comment tu gère ton projet (quel IDE ? comment tu compile tes fichiers : à la main , avec cmake avec un makefile, etc..). Mais l'erreur est clairement que une de tes fonctions de ton projet n'a pas été compilée (j'enfonce des portes ouvertes je sais). Cela peut-être du à plusieurs chose:

      - Tu n'as pas inclus le fichier contenant la définition de la fonction manquante à ton projet, ce qui fait que le fichier n'est pas compilé et donc que la fonction n'est pas trouvable par le compilateur au moment de l' édition des liens.

      - D'autres raisons peut-être , mais comme tu ne donnes pas beaucoup d'infos sur la manière de compiler ton projet...:)

      • Partager sur Facebook
      • Partager sur Twitter

      Mon site web de jeux SDL2 entre autres : https://www.ant01.fr

        18 novembre 2021 à 23:06:29

        Bonjour,

        La fonction qui manque est une fonction-template, et la fonction que tu montres ne l'est pas. La template pourrait avoir cette forme:

        template<class T=std::vector<Entity>&> T allEntities();

        Vérifie tes fichiers d'entête

        • Partager sur Facebook
        • Partager sur Twitter

        En recherche d'emploi.

          19 novembre 2021 à 9:33:30

          @Warren79 niveau compilation j'utilise Code::Blocks, qui gère la compilation, tout ce dont je peux être sûr c'est que je compile en C++17 x) Si y'a un moyen de récupérer un fichier/une ligne de compilation sur Code::Blocks je pourrais t'envoyer ça

          @Dalfab j'avais déjà mis la template suivante :

          template<typename T = std::vector<Entity>> T& allEntities();

          Mais j'avais un souci avec autre chose je sais plus exactement quoi, je ressaie ce soir quand je suis chez moi et je te dis quoi

          UPDATE :

          @Dalfab : j'ai mis comme tu m'as dit, mais j'ai toujours la même erreur, c'est-à-dire :

          |undefined reference to `std::vector<Entity, std::allocator<Entity> >& allEntities<std::vector<Entity, std::allocator<Entity> >&>()'|

          J'ai écrit ma fonction et son entête comme ça :

          //entete
          template<class T = std::vector<Entity>>
          T& allEntities();
          
          //corps
          template<class T = std::vector<Entity>>
          T& allEntities() {
              static T entities;
              return entities;
          }

          Une idée de comment je pourrais régler le problème ? ^^'

          -
          Edité par EthanWright 19 novembre 2021 à 19:19:41

          • Partager sur Facebook
          • Partager sur Twitter
            20 novembre 2021 à 10:38:51

            Bonjour,

            Je ne sais pas pourquoi il faudrait mettre la fonction sous une forme template?
            Si c'est vraiment ton besoin, la fonction template doit être impérativement définie dans l'entête, elle ne doit pas être dans le cpp. Car le corps de la fonction doit être visible de tous les endroits où on veut instancier la fonction-template. Et le paramètre par défaut du template ne doit pas être répété dans la définition.

            Donc:

            // entete
            template<class T = std::vector<Entity>>
            T&  allEntities();
             
            // AUSSI DANS l'ENTETE
            template<class T>
            inline T&  allEntities() {
                static T  entities;
                return entities;
            }

            ou fonction non template:

            // entete
            std::vector<Entity>&  allEntities();
             
            // corps
            std::vector<Entity>&  allEntities() {
                static std::vector<Entity>  entities;
                return entities;
            }

            -
            Edité par Dalfab 20 novembre 2021 à 10:40:14

            • Partager sur Facebook
            • Partager sur Twitter

            En recherche d'emploi.

              22 novembre 2021 à 14:43:39

              D'accord, merci pour l'aide ! Par contre, il y a un truc que je ne comprends pas trop, c'est le "inline", même après lecture de sa page sur cppreference j'ai encore du mal avec, à quoi sert-il ?

              Merci encore pour l'aide ! Et désolé de répondre 2 jours après :p

              • Partager sur Facebook
              • Partager sur Twitter
                23 novembre 2021 à 1:16:17

                Bonjour,

                cppreference, c'est le Site pour avoir des informations exactes. C'est quasi identique à lire la norme, c'est précis mais du coup ça manque forcément un peu de pédagogie.

                Pour comprendre inline, il faut peut-être d'abord comprendre ce qu'est le "one definition rule". Tout ce qui est défini ne doit l'être qu'une seule et unique fois. Car sinon on aurait le potentiellement 2 définitions de la même chose, avec des tas de boulot pour le compilateur et le l'éditeur des liens pour vérifier que les définitions sont totalement identiques. C'est pour cette raison que les définitions de variables et de fonctions doivent toujours être dans un fichier source. Pour les types ils peuvent être sans les entêtes car ils n'existent pas pour l'édition des liens, et ils sont garantis uniques à chaque unité de compilation grâce aux #define que l'on met au début des entêtes.

                Mais il y a des exceptions.
                - une variable ou une fonction définie inline peut être définie à plusieurs endroits. La définition doit être strictement identique mais malheureusement l'éditeur des liens ne peut normalement pas effectuer ce contrôle. 
                - les template<> eux aussi peuvent être vus plusieurs fois. C'est une exception indispensable car ils doivent être visibles de tous les points où il sont instanciés.
                - Pour certaines classes, j'ai un peu simplifié avant, le compilateur et l'éditeur des liens doivent s'entendre car ils ont besoins de données internes qui rompent le "one definition rule" (typeinfo(), membres spéciaux et la vtable) mais c'est transparent aux utilisateurs.

                Donc dans ces deux premiers cas, il y a risques et il y a boulot supplémentaire pour le compilateur. Il faut donc éviter leur utilisation, et là c'est surtout les fichiers sources qui sont à risque. Tout inline ou template<> dans un source peut amener à des bugs difficiles à résoudre.

                On doit donc utiliser les inline avec parcimonie.

                Les fonctions inline sont intéressantes car elles vont permettre une meilleure optimisation du code. Et ceci essentiellement quand la fonction est très courte. Et toutes les fonctions membres non static définies dans le corps d'une classe sont en fait inline même s'il n'y a pas le mot inline avant, là aussi c'est bien pour les petites fonctions et à éviter pour les grandes.

                • Partager sur Facebook
                • Partager sur Twitter

                En recherche d'emploi.

                  23 novembre 2021 à 11:10:20

                  Inline devant un template ne sert à rien.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    23 novembre 2021 à 15:31:58

                    SpaceIn a écrit:

                    Inline devant un template ne sert à rien.

                    Tout à fait, je l'ai mis par une ancienne habitude. Avant les fonctions-template n'étaient pas développées en ligne, et le mot inline quant à lui forçait une fonction a être développée en ligne. Désormais le compilateur fait lui-même ce choix d'optimisation qu'elle que soit la fonction. D'ailleurs le mot-clef inline vient bien de là:)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    En recherche d'emploi.

                    undefined reference to `fonction`

                    × 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