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

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

Langage C++ Discussion :

Template Pointeur Vector


Sujet :

Langage C++

  1. #1
    Membre averti
    Homme Profil pro
    L3 Informatique
    Inscrit en
    Avril 2020
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : L3 Informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2020
    Messages : 29
    Par défaut Template Pointeur Vector
    Bonjour,

    Je suis bloqué dans la réalisation d'un TP.

    Voici le contexte, j'ai 2 classes : Core et MapReduce.

    Je chercher à avoir vecteur de pointeurs de Core statique qui contiendra 4 instances de Core dans MapReduce.

    Voici le main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    #include <iostream>
     
    #include "Core.cpp"
    #include "MapReduce.cpp"
     
    int main(int argc, char **argv) {
     
        std::vector<int> b = std::vector<int>({12, 3, 100, 60, -7, -8, -9, -10});
     
        MapReduce<int> mri(&b);
     
        // 0- Affichage du nombre de coeurs initiaux
        std::cout << std::endl << "####### test 0 #######" << std::endl;
        std::cout << std::endl << "Nombre de coeurs initiaux: " << Core<int>::getCount() << std::endl;
     
        //1- Décommentez pour tester si on peut instancier un nouveau coeur (ne doit pas fonctionnerer)
        //Core<int> core1;
     
        //2 - Test d'affichage des coeurs disponibles (id s'incrémente et degradation 0)
        std::cout << std::endl << "####### test 2 #######" << std::endl << std::endl;
        MapReduce<int>::afficherCores();
     
        return 0;
    }
    Core.hpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    #ifndef CORE
    #define CORE
     
    #include <vector>
    #include <iostream>
     
    template<typename T>
    class Core {
    private:
        static int counter;
        static int identifiant;
        const int id;
        int degradation;
        std::vector<T> *values;
        Core(): id(++identifiant) {
            degradation = 0;
            ++counter;
        }
    public:
        static int getCount(){
            return counter;
        }
        int getID(){
            return id;
        }
        int getDE(){
            return degradation;
        }
    };
     
    #endif
    Core.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include "Core.hpp"
     
    template<typename T>
    int Core<T>::identifiant = 0;
     
    template<typename T>
    int Core<T>::counter = 0;
    MapReduce.hpp

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    #ifndef MAPREDUCE
    #define MAPREDUCE
     
     
    #include <vector>
    #include <iostream>
     
    #include "Core.hpp"
     
    template<typename T>
     
    class MapReduce {
    private:
        const static std::vector<Core<T> *> cores{
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{})
        };
        std::vector<Core<T>> *values;
        Core<T> * core;
    public:
        explicit MapReduce(std::vector<int> *pVector){
            for (const std::vector<Core<T> *> &item : cores) {
                // erreur : In template: reference to type 'const std::vector<Core<int> *>' could not bind to an lvalue of type 'Core<int> *const'
            }
        }
     
        static void afficherCores(){
            for(int i = 0; i < cores.size(); i++){
                std::cout << "id : " << cores.at(i)->getID() << std::endl;
     
                // erreur : In template: no matching member function for call to 'push_back'
            }
        }
    };
     
     
    #endif
    J'obtiens les deux erreurs ci-dessus, du coup impossible d'instancier mes core et d'obtenir le resultat de getcount() et afficherCores().

    J’espère que vous pourrez m'aider, merci par avance.

  2. #2
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2019
    Messages
    108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2019
    Messages : 108
    Par défaut
    Bonjour,

    À la ligne 5 du main t'as inclu MapReduce.cpp au lieu de MapReduce.hpp.

    Dans MapReduce.hpp tu ne peux pas faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        const static std::vector<Core<T> *> cores{
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{})
        };
    déjà push_back ne renvoie rien (void) et en plus cores est entrain d'être déclaré (n'existe pas encore).

    Je pense que tu voulais faire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        const static std::vector<Core<T> *> cores{
                Core<T>{},
                Core<T>{},
                Core<T>{},
                Core<T>{}
        };
    et encore ça ne marchera pas, Core n'a pas de constructeur public. Core a un constructeur (constructeur par défaut) et il est privé, le seul moyen de l'instancier est d'être amie.

    Dans Core.cpp, le code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<typename T>
    int Core<T>::identifiant = 0;
     
    template<typename T>
    int Core<T>::counter = 0;
    n'a aucun effet, ça ne marchera pas.

    J'ai pas voulu aller plus loin ça en fait déjà trop

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,
    1-
    Citation Envoyé par JeanPPPP Voir le message
    Je suis bloqué dans la réalisation d'un TP.
    Bon, déjà, il faut savoir que, si l'on peut t'aider dans les choix que tu fais, dans la manière d'obtenir un résultat donné, on ne fera jamais ton travail à ta place...

    D'autant moins s'il s'agit d'un TP, car ce serait un très mauvais service à te rendre

    2-
    Je chercher à avoir vecteur de pointeurs de Core statique qui contiendra 4 instances de Core dans MapReduce.
    A- pourquoi un vecteur de pointeurs pourquoi pas un vecteur de Core

    NOTA: si le nombre d'éléments est déterminé une bonne fois pour toutes et qu'il ne bougera plus jamais (et surtout pas à l'exécution), l'utilisation d'un std::array pourrait s’avérer intéressante

    B- Pourquoi veux tu rendre ce vecteur de pointeurs statique

    Car, qui dit donnée statique dit donnée globale, et qui dit donnée globale dit souvent défaut de conception (dans le meilleur des cas) et problèmes en pagaille à cause de la globalité de la donnée (de manière systématique).

    C- Dans quel ordre les Core, les MapReduce et le tableau de (pointeurs sur) Core devront ils être générés / traités

    3-
    Core.hpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    #ifndef CORE
    #define CORE
     
    #include <vector>
    #include <iostream>
     
    template<typename T>
    class Core {
    private:
        static int counter;
        static int identifiant;
        const int id;
        int degradation;
        std::vector<T> *values;
        Core(): id(++identifiant) {
            degradation = 0;
            ++counter;
        }
    public:
        static int getCount(){
            return counter;
        }
        int getID(){
            return id;
        }
        int getDE(){
            return degradation;
        }
    };
     
    #endif
    pfffff.... Le Core qui se charge tout seul de gérer le nombre de Core qui existent, c'est ... plutôt scabreux comme histoire...

    Le principe de la responsabilité unique nous indique en effet que chaque type de donnée, chaque donnée, chaque fonction ne devrait en permanence n'avoir à s'occuper que d'une seule et unique chose.

    La notion de Core, quelle qu'elle soit, ne devrait donc avoir à s'occuper que des affaires de Core.

    La gestion des identifiants assignés aux différents Core qui existe devrait donc être dévolue à ... autre chose. Elle peut se faire de manière tout à fait basique, et se contenter de fournir un identifiant que l'on garantira unique lors de la création d'un Core (en "perdant" les identifiants des Core qui cessent d'exister / qui sont détruits), ou être "plus élaborée" (en permettant la réutilisation des identifiants de Core's qui ont cessé d'exister), au choix, mais ce n'est pas le Core qui devrait s'en charger, quoi qu'il en soit

    B-l'inclusion de <iostream> ne sert ici à rien ...

    Essaye de prendre l'habitude de n'inclure que les fichiers qui sont strictement indispensables et, de préférence, uniquement lorsqu'ils deviennent absolument indispensables.

    Cela ne changera sans doute pas grand chose pour des "petits" projets comme celui-ci, mais tu te rendras assez rapidement compte avec de l'expérience sur des (très) "gros" projet (plusieurs dizaines ou centaines de milliers de fichiers) que la compilation peut très rapidement commencer à prendre plus ou moins de temps, en fonction du nombre de fichiers que tu inclus inutilement

    4-
    Core.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include "Core.hpp"
     
    template<typename T>
    int Core<T>::identifiant = 0;
     
    template<typename T>
    int Core<T>::counter = 0;
    Ah, ben oui... Ben, en fait, tout le problème vient de là...

    Car comme le terme l'indique, les template ne fournissent que des "modèles de fonctionnement".

    Or, le compilateur ne peut pas se permettre de générer le code binaire exécutable basé sur ces modèles de fonctionnement adapté à chacun des treize types élémentaires et des 3 000 types définis par l'utilisateur utilisés par ton projet.

    Il va, en fait, attendre de savoir avec quel type de donnée exactement le modèle qu'on lu a fourni sera utilisé avant de générer le code binaire exécutable adapté à ce type de donnée particulier.

    Pour faire simple, il va devoir attendre de savoir à quel type de donnée correspond ce type que l'on a appelé T dans le code avant de décider de générer le code binaire exécutable correspondant au modèle prévu spécifiquement pour fonctionner avec le type identifié comme étant "le type T" dans le modèle.

    Mais cela signifie qu'il doit disposer de ... tout ce qui lui permettra de générer l'intégralité du code binaire exécutable adapté au type T une fois qu'il saura à quel type de donnée ce T correspond effectivement.

    Si bien que le code que tu as "logiquement" mis (par habitude sans doute) dans Core.cpp devrait, en réalité, être fourni à chaque endroit du code où tu indique au compilateur que tu veux manipuler ta classe Core avec un T particulier.

    Pour faire simple, ce code là devrait aussi (parce que tu travaille avec des template) se trouver dans le fichier Core.hpp

    C'est, du moins, la manière la plus simple que tu trouveras pour garantir que ce code soit également disponible au moment où le compilateur rencontrera la ligne
    std::cout << std::endl << "Nombre de coeurs initiaux: " << Core<int>::getCount() << std::endl; (qui lui demande explicitement de générer un Core avec T correspondant à int ) grace à l'inclusion de code qui a lieu au moment de la ligne #include "Core.hpp"(NOTA: il y a d'autres manières de s'y prendre, mais j'ai choisi la plus simple à expliquer et à mettre en oeuvre )

    5-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    /*...*/
    template<typename T>
     
    class MapReduce {
    private:
        const static std::vector<Core<T> *> cores{
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{}),
                cores.push_back(Core<T>{})
        };
    Oulàh...

    Tu déclares la donnée cores comme étant un tableau (std::vector) de pointeurs sur des donées de type Core<T> (Core<T>*).

    Mais tu essaye d'y faire entrer des (valeurs de type)... Core<T>. Cherchez l'erreur :-$

    Pour rappel, un pointeur n'est jamais qu'une valeur numérique entière (généralement non signée) correspondant à l'adresse mémoire à laquelle on (espère que l'on) trouvera une donnée du type indiqué.

    Il y a donc, très clairement, quelque chose qui ne va pas dans l'histoire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public:
        explicit MapReduce(std::vector<int> *pVector){
            for (const std::vector<Core<T> *> &item : cores) {
                // erreur : In template: reference to type 'const std::vector<Core<int> *>' could not bind to an lvalue of type 'Core<int> *const'
            }
        }
    Ben oui, cores est ta donnée de type std::vector<Core<int>*>.

    Cela signifie que les éléments sur lesquels on va itérer et que l'on obtiendra depuis cores ce sont des ... Core<int>*. item est donc bel et bien un /* const */Core<int>*, voire un /*const */ Core<int>* &NOTA:

    Quitte (et tu as parfaitement raison de le faire) à entrer dans "l'air moderne du C++" avec les range based loops (car for(Type element : collection) n'est arrivé qu'avec C++11), pourquoi ne pas entrer carrément dans cette air moderne et décider d'utiliser l'inférence de type grâce à la nouvelle signification (apparue elle aussi en C++11) du mot clé auto qui, il faut bien l'avouer ici, t'éviterait sans doute bien du soucis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        static void afficherCores(){
            for(int i = 0; i < cores.size(); i++){
                std::cout << "id : " << cores.at(i)->getID() << std::endl;
     
                // erreur : In template: no matching member function for call to 'push_back'
            }
        }
    };
    Ne t'en fais pas pour cette erreur là, qui a de très fortes chances d'apparaitre en fait parce que tu as fait "perdre les pédales" au compilateur.

    Je peux me tromper (car je n'ai pas tenté d'apporter les corrections nécessaires à ton code), mais je suis près à parier (toute ma sympathie ) que, si tu corrige les erreurs qui apparaissent avant, cette erreur particulière disparaitra "comme par enchantement", du simple fait que le compilateur aura "gardé le fil" de ce qu'il est occupé à faire
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. template, pointeur de fonction et déclaration
    Par mensoif dans le forum Langage
    Réponses: 4
    Dernier message: 01/06/2010, 00h31
  2. [Template] Pointeur sur classe template
    Par Kromagg dans le forum Langage
    Réponses: 2
    Dernier message: 29/10/2008, 16h01
  3. Template & pointeurs
    Par Apocalipsia` dans le forum Langage
    Réponses: 24
    Dernier message: 18/07/2008, 09h04
  4. Templates, pointeurs et égalités
    Par Romaincb dans le forum C++
    Réponses: 9
    Dernier message: 12/03/2007, 09h58
  5. Réponses: 13
    Dernier message: 03/10/2005, 18h06

Partager

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