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

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

C++ Discussion :

Problème de template (encore..)


Sujet :

C++

  1. #21
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Ok j'ai bien compris la procédure à suivre mais j'ai une dernière question. Tu m'as dit en gros "J'espère que tu n'as pas fait ça". Mais comment faire alors pour stocker la valeur d'un type inconnu? Quel type utiliser?

  2. #22
    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
    Ben, tu utilises un template

    A l'extrême limite, la valeur de la donnée "d'origine" peut tout à fait se trouver dans la structure qui représente les informations codées en 64 bits, après tout, le codage 64 bits et la valeur d'origine ne sont jamais que des représentation différente d'une seule et même donnée

    Si je reprend la structure (sous forme de template) "simplifiée (je laisse tomber les rangs et ce qui fait parasite dans l'histoire , tu peux très bien avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <typename Type>
    struct Data{
        /* ca, c'est juste pour pouvoir récupérer le type en cas de besoin ;) */
        usign value_type = Type ;
        enum{accessSize = sizeof(Type)}; // la taille réellement utilisée en mémoire par Type (en bytes ;) )
        value_type original; // la valeur d'origine (dans son type d'origine)
     
        unsigned char transformed[sizeof(uint64_t)];//la représentation en 64 bits
        /** lsb et tous les autres */
    };
    Les trois premières lignes significatives te permettent d'avoir toutes les informations dont tu peux avoir besoin au niveau du type de donnée à convertir, dans l'ordre
    1. Le type de la donnée
    2. le nombre de bytes utilisés en mémoire pour la représenter
    3. la valeur avant conversion et manipulation

    La quatrième ligne correspond au résultat après manipulation (en 64 bits)

    Une fois que tu as cela, tu n'as plus qu'à transmettre ton objet de type Data <n'importe quel type> à une fonction ou à une classe template pour que tout tourne tout seul

    Fais juste attention à un fait particulier: Cette structure accepterait sans aucun problème d'être spécialisée avec la structure personne que je présentais quelques interventions plus tôt...

    Mais une telle structure est beaucoup trop grande pour tenir sur 64 bits
    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

  3. #23
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Encore merci de tes éclaircissements Hélas je ne sais pas si c'est parce qu'on est lundi matin mais j'ai pas compris grand chose à ta structure

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <typename Type>
    // Ca c'est la nouveauté

    // No comment, cava

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    usign value_type = type;
    // Ligne que j'ai vraiment pas compris D'où sort value_type et type;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    enum{accessSize = sizeof(Type)};
    // Juste une question : pourquoi un enum?

    // Ca sert a quoi?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char transformed[sizeof(uint64_t)];
    // J'ai envie de dire pareil

    Désolé si je te fais répéter mais ce serait c** de par comprendre la conclusion

    Pourquoi pas tout simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename Type>
    {
    Type value;
    unsigned int accessSize = sizeof(Type);
    /*Reste*/
    };

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Encore merci de tes éclaircissements Hélas je ne sais pas si c'est parce qu'on est lundi matin mais j'ai pas compris grand chose à ta structure

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template <typename Type>
    // Ca c'est la nouveauté
    Dans mes interventions précédentes je te disais d'utiliser une structure template.

    Il est cependant vrai que j'utilisais d'abord la structure var je crois
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    usign value_type = type;
    // Ligne que j'ai vraiment pas compris D'où sort value_type et type;
    une coquille de ma part. Il fallait lire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    using value_type = Type;
    Je corriges dans mon code

    Sinon, typedef est déprécié au profit de using en C++11.

    Quand typedef s'utilise sous la forme de typedef <type d origine > <alias pour le type>; using s'utilise sous la forme de using <alias pour le type> = <type d origine>; et permet de définir un "template typedef" (un alias qui est malgré tout encore un template, et qui spécialise partiellement un autre type template).

    Cette ligne permet juste d'avoir un alias de type (value_type) qui correspond au paramètre template fourni
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    enum{accessSize = sizeof(Type)};
    // Juste une question : pourquoi un enum?
    Parce que cela en fait une constante de compilation.

    L'autre solution aurait consisté à le définir comme une variable statique constante, mais je préfères l'énumération "par habitude"
    // Ca sert a quoi?
    C'est la valeur d'origine (celle que l'utilisateur manipule).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char transformed[sizeof(uint64_t)];
    // J'ai envie de dire pareil
    C'est le tableau de caractères que tu remplis lors de la conversion.

    J'utilise un tableau de taille fixe pour que l'on ne doive pas s'inquiéter de l'allocation dynamique de la mémoire.

    Je définis le nombre d'éléments à sizeof(uint64_t) pour éviter de faire la moindre supposition quant au nombre réel de bytes utilisés par une uint64_t. En effet, la seule chose dont on ait l'absolue certitude, c'est que sizeof(char) vaut 1 et que sizof(n'importe quel autre type primitif) aura une valeur qui est un multiple de 1
    Désolé si je te fais répéter mais ce serait c** de par comprendre la conclusion
    Je n'ai aucun problème à ce sujet là
    Pourquoi pas tout simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename Type>
    {
    Type value;
    unsigned int accessSize = sizeof(Type);
    /*Reste*/
    };
    Cela revient effectivement au même.

    La seule différence, c'est que j'ai défini un alias pour Type qui me permet de récupérer le type de la valeur fournie par l'utilisateur, et que j'ai donc utilisé ce type quand j'en avais besoin.

    L'idée de base qui sous tend l'utilisation d'un alias de type est simplement qu'il te permet éventuellement de récupérer le type réel de la valeur quand tu es dans une fonction template.

    Tu pourrais en effet envisager une fonction proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    void foo(Data<T> /* const &*/ data){
    /* sans l'alias "value_type", si je veux récupérer le type réel de T, je fais comment ? */
    /*je met quoi ici??? */ brol = data.original;
    }
    Si tu définis un alias de type qui correspond au paramètre template, tu peux le faire sans difficulté:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void foo(Data<T> /* const &*/ data){
    Data<T>:value_type  brol = data.original;
    }
    L'idée de base est qu'un type personnalisé ou une fonction ne vaut jamais que par l'utilisation qui en est faite parce qu'un type personnalisé ou une fonction qui ne serait jamais utilisé n'aurait absolument aucun intérêt.

    Comme il est difficile de prédire tous les cas d'utilisations que l'on pourra faire d'une structure template, il est préférable de prévoir le cas où l'on aurait besoin de travailler de manière spécifique sur le type particulier du paramètre template à un moment particulier.

    Cela ne mange pas de pain, mais pourra te sortir de certaines situations difficiles
    [EDIT]Tu pourrais d'ailleurs parfaitement envisager de créer une structure qui se contenterait de définir un certain nombre d'alias de types sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    template<typename T>
    struct MyTraits{
        using type = T;               // le type lui-même, par valeur
        using ref_type = T &;         // le type par référence non constante
        using cef_type = T const &;   // le type par référence constante
        using ptr_type = T *;         // le type par pointeur
        usign ptr_diff   = sizeof(T); // l'espace mémoire qui sépare deux variables contigues de même type
    };
    qui pourrait parfaitement être utilisé sous une forme proche de
    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
    template <typename T>
    void foo(T /* const & */ t){
       MyTraits<T>::type t2 = t; // "copie" de t
       MyTraits<T>::ref_type ref = t; // une référence sur t
       MyTraits<T>::cref_type cref = t; // une référence constante sur t
       MyTraits<T>::ptr_type ptr = &t; // un pointeur sur t
    }
    template <typename T>
    void bar(std::vector <T> & tab){
        std::ofstream ofs("out.bin",std::ios::binary);
        char * charTab = reinterpret_cast<char*>(&tab[0]);//je considère le tableau comme étant un tableau de char
        size_t count = tab.size(); // je sais qu'il contient count éléments de type T
        size_t tsize = MyTraits<T>::ptr_diff; // la taille d'un élément (en nombre de bytes)
        for(size_t i = 0;i<count;++i) {// je veux passer tous les éléments en revue
            ofs.write(&charTab[i*tsize],tsize);
        }
        /* bon, il est vrai qu'il aurait sans doute été plus facile de faire
         * ofs.write(&charTab[0],count*size); 
         * mais c'était pour l'exemple :D
         */
    };
    /* une structure (mode C pour la cause) */
    struct Personne{
    char nom[15];
    char prenom[15];
    };
    int main(){
        std::vector<Personne> tab; 
        /* remplissage de tab */
        foo<Personne>(tab[3]);
        bar<Personne>(tab);
    }
    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

  5. #25
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Merci encore koala01 pour ces explications

    Déjà j'ai essayé dans un petit projet vide, de définir la structure template comme tu me l'as dit mais la ligne avec le using pose problème (expected nested-name-specifier before 'value_type')

    De plus, j'ai voulu utiliser les template pour ne pas devoir faire une batterie de if pour au final faire la même chose mais je pense que je vais pas pour en échapper même si j'arrive à définir cette structure

    Car quand je vais l'instancier il va bien falloir que je fasse un truc du genre :
    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
    if (utilisateur a choisit de créer un entier signé)
    {
    if (il en veut un de taille de 1 byte)
    instanciation de la structure avec int8
    if (il en veut un de taille de 2 bytes)
    instanciation de la structure avec int16
    ...
    }
    if (utilisateur a choisit de créer un entier non signé)
    {
    f (il en veut un de taille de 1 byte)
    instanciation de la structure avec uint8
    if (il en veut un de taille de 2 bytes)
    instanciation de la structure avec uint16
    ...
    }
    pareil pour le type enum, float, bool...
    C'est fou comme j'aurai du bien réfléchir et demander des avis avant de me lancer de d'en être la car maintenant j'ai l'impression d'être f**ked

  6. #26
    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
    En fait, un code proche de usign unNom = unType; ne fonctionne qu'en C++11, mais est équivalent (avec quelques joyeusetés en plus) à typdef unType unNom;Evidemment, pour pouvoir utiliser cette fonctionnalité, il faut que le compilateur la supporte (et je ne sais pas du tout si c'est le cas de Visual Studio, par exemple )

    Mais, mis à part cette particularité, tout ce que j'ai expliqué jusqu'ici reste tout à fait valable, même avec un compilateur qui ne supporte que l'ancienne norme, et l'utilisation des template a, justement, pour but de t'éviter d'avoir à tester ce que le compilateur connait bien mieux que toi.

    Si la structure sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <typename Type>
    struct Data{
        /* ca, c'est juste pour pouvoir récupérer le type en cas de besoin ;) */
        usign value_type = Type ;
        enum{accessSize = sizeof(Type)}; // la taille réellement utilisée en mémoire par Type (en bytes ;) )
        value_type original; // la valeur d'origine (dans son type d'origine)
     
        unsigned char transformed[sizeof(uint64_t)];//la représentation en 64 bits
        /** lsb et tous les autres */
    };
    refuse de compiler à cause de la directive usign, ce n'est pas bien grave, travaillons avec des typedef, et essayons sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template <typename Type>
    struct Data{
        /* ca, c'est juste pour pouvoir récupérer le type en cas de besoin ;) */
        typedef Type value_type;
        enum{accessSize = sizeof(Type)}; // la taille réellement utilisée en mémoire par Type (en bytes ;) )
        value_type original; // la valeur d'origine (dans son type d'origine)
     
        unsigned char transformed[sizeof(uint64_t)];//la représentation en 64 bits
        /** lsb et tous les autres */
    };
    (dans le cas présent, j'essayais juste d'éviter le recours au typedef car il a été déprécié, ce qui signifie que l'on peut s'attendre, à terme, à ce qu'il soit purement et simplement retiré )

    Mais un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main(){
        Data<char> dc; // dc::value_type = char , dc::accessSize = 1 
        Data<short> ds; // ds::value_type = short, dc::accessSize = (sans doute) 2
        Data<int> di; // di::value_type = int, dc::accessSize = (sans doute) 4
        std::cout<< dc.accessSize <<" "<<ds.accessSize <<" "<<di.accessSize
                 <<std::endl;
    }
    te convaincra sans doute que c'est bel et bien ce que tu souhaites
    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

  7. #27
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Ok super !

    Tu me conseilles donc de faire concorder l'acessSize avec la vrai taille du type alors et ca lors de la création de la donnée (si j'ai bien compris)

    Il me faudra toujours ma batterie de if-else if mais au moins ce sera fait, c'est ca ?

    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
    if (utilisateur a choisit de créer un entier signé)
    {
    if (il en veut un de taille de 1 byte)
    Data<int8_t> dc;
    if (il en veut un de taille de 2 bytes)
    Data<int16_t> dc;
    ...
    }
    if (utilisateur a choisit de créer un entier non signé)
    {
    if (il en veut un de taille de 1 byte)
    Data<uint8_t> dc;
    if (il en veut un de taille de 2 bytes)
    Data<uint16_t> dc;
    ...
    }
    Et la j'aurai plus qu'à utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <class T>
    void read(T& val, const unsigned char* data, int msb, int lsb, bool big_endian=true)
    {
        const size_t size = sizeof(T);
        typedef typename unsigned_<size>::type type;
        type *ptr = reinterpret_cast<type*>(&val);
        for(size_t i=0; i<size; ++i)
            ptr[big_endian ? size-i-1: i] = data[i];
        val <<= (sizeof(val) * CHAR_BIT - msb - 1);
        val >>= lsb;
    }
    //et de l'appeler comme cela :
    read(dc.original, ...);
    Et tout sera réglé. (Enfin j'espère )

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Ok super !

    Tu me conseilles donc de faire concorder l'acessSize avec la vrai taille du type alors et ca lors de la création de la donnée (si j'ai bien compris)
    oui, tout à fait
    Il me faudra toujours ma batterie de if-else if mais au moins ce sera fait, c'est ca ?

    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
    if (utilisateur a choisit de créer un entier signé)
    {
    if (il en veut un de taille de 1 byte)
    Data<int8_t> dc;
    if (il en veut un de taille de 2 bytes)
    Data<int16_t> dc;
    ...
    }
    if (utilisateur a choisit de créer un entier non signé)
    {
    if (il en veut un de taille de 1 byte)
    Data<uint8_t> dc;
    if (il en veut un de taille de 2 bytes)
    Data<uint16_t> dc;
    ...
    }
    Mais, justement, non!!!

    Tu n'as absolument pas besoin de faire cette batterie de tests!!!

    Si tu compiles le code de mon intervention précédente, tu te rendras compte que la taille indiquée correspond bel et bien au type que l'utilsateur a décidé duiliser
    Et la j'aurai plus qu'à utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template <class T>
    void read(T& val, const unsigned char* data, int msb, int lsb, bool big_endian=true)
    {
        const size_t size = sizeof(T);
        typedef typename unsigned_<size>::type type;
        type *ptr = reinterpret_cast<type*>(&val);
        for(size_t i=0; i<size; ++i)
            ptr[big_endian ? size-i-1: i] = data[i];
        val <<= (sizeof(val) * CHAR_BIT - msb - 1);
        val >>= lsb;
    }
    //et de l'appeler comme cela :
    read(dc.original, ...);
    Et tout sera réglé. (Enfin j'espère )
    En fait, je te conseille carrément de ne transmettre que la structure, en un seul paramètre, et donc sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template <typename T>
    void read(Data<T> /* const */ & data){
      /* tu utilise les membres de data ici */
    }
    Ce sera bien plus facile, et bien plus efficace
    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

  9. #29
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Désolé koala01 de répéter ça mais je suis obligé de faire cette batterie de tests !
    Quand l'utilisateur crée une donnée, il le fait via une GUI qui ressemble à Excel : chaque ligne est une donnée et chaque colonne une info (nom de la donnée, accessSize, type, valeur, lsb, toussa toussa).
    Pour l'accessSize c'est une comboBox (1, 2, 4, 8) et pour le type aussi (bool, enum, entier signé, entier non signé).
    Une fois qu'il valide, en interne je me retrouve avec pleins d'informations par ligne que je dois stocker et il faut bien que je fasse le lien entre le type et la taille pour en déduire le type T pour lui assigner la valeur.
    Par exemple, si il a choisi type = entier signé et taille d'accès 4 bytes bah je fais Data<int32_t> dc; et hop je remplis la structure !
    Enfin je vois pas comment faire autrement

  10. #30
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut

    Une dernière réponse et je serai fixé

    Non en fait je mens J'ai juste besoin d'une dernière confirmation

    Si on prend la structure que koala01 m'a conseillé d'utiliser. J'aimerai savoir si je peux faire une liste de cette structure (std::vector, QVector, etc..) ? Car étant de taille inconnue (la structure hein) je me demande comment cela peut marcher !

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Désolé koala01 de répéter ça mais je suis obligé de faire cette batterie de tests !
    Quand l'utilisateur crée une donnée, il le fait via une GUI qui ressemble à Excel : chaque ligne est une donnée et chaque colonne une info (nom de la donnée, accessSize, type, valeur, lsb, toussa toussa).
    Pour l'accessSize c'est une comboBox (1, 2, 4, 8) et pour le type aussi (bool, enum, entier signé, entier non signé).
    Une fois qu'il valide, en interne je me retrouve avec pleins d'informations par ligne que je dois stocker et il faut bien que je fasse le lien entre le type et la taille pour en déduire le type T pour lui assigner la valeur.
    Par exemple, si il a choisi type = entier signé et taille d'accès 4 bytes bah je fais Data<int32_t> dc; et hop je remplis la structure !
    Enfin je vois pas comment faire autrement
    En fait, on travaille ici sur l'aspect "business" uniquement, ou, si tu préfères, sur le coté "modèle" de ton application.

    Je crois déjà avoir insisté auprès de toi sur l'impérative nécessité de séparer clairement la partie métier de la partie purement "représentative" pour l'utilisateur et de la partie qui s'assure que l'utilisateur ne fait pas de conneries avant d'envoyer ses ordres à la partie métier.

    au niveau de ta fonction d'encodage, tu n'as absolument pas à t'inquiéter d'autre chose que du type effectif, et tu n'as donc absolument pas besoin (au niveau de la partie métier du moins) de commencer à faire le moindre test pour savoir ce qui correspond le mieux

    Par contre, au niveau de l'IHM, c'est l'utilisateur lui-même qui devrait décider du type réel de la donnée qu'il veut encoder, au moment où il construit sa table.

    Pour la création de la table, tu devrais donc fournir un "combobox" qui reprend les différents types possible (pour l'instant, on va dire les 13 types primitifs).

    Sur base de cette information (fournie par l'utilisateur!!!), tu n'auras même pas à t'inquiéter de la taille de la donnée, tu n'auras qu'à... indiquer clairement le type qui spécialise la structure en fonction de l'index sélectionné du combobox.

    Je m'explique:

    Tu devrais fournir un combobox qui donne le choix entre char, unsigned char, short, unsigned short, int, unsigned int et tous les autres.

    Tu pourrais alors avoir un simple switch case qui fonctionne sous la forme de
    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
    switch( selectedIndex){
        case 1:
            Data<char> d;
            /* transmission à un système template qui l'utilise */
            break;
        case 2:
            Data<unsigned char> d;
            /* transmission à un système template qui l'utilise */
            break;
        case 3:
            Data<short> d;
            /* transmission à un système template qui l'utilise */
            break;
        /* et ainsi de suite */
    }
    Et le controleur devrait, au moment où l'utilisateur remplit la table, s'assurer que la donnée introduite par l'utilisateur correspond bel et bien au type que ta table attend pour un champs donné.

    Les IHM vont, en effet, essentiellement travailler sur des valeurs sous forme de chaines de caractères.

    Il faudra donc que tu vérifies si la valeur représentée par cette chaine de caractères correspond bel et bien au type qui est attendu pour le champs particulier de la table pour lequel l'utilisateur est sensé donner une valeur.

    Le type (unsigned) char excepté (car il serait plutôt représenté par le caractère ASCII (ou un caractère de tout autre jeux de caractères) que par une valeur numérique), tu devras vérifier si la valeur entre dans l'intervalle correspondant au type de la donnée.

    Tu devras alors commencer les vérification en testant la présence d'un ., d'un E ou d'un e dans la chaine de caractères, afin de savoir si l'on part du principe qu'il s'agit d'un réel ou d'un entier.

    S'il s'agit d'un entier, tu peux le convertir d'office en long long (le plus grand type primitif capable de représenter des valeurs entières), et s'il s'agit d'un réel, tu peux le convertir d'office en long double (le plus grand type primitif capable de représenter des valeurs réelles).

    La dernière vérification à effectuer, une fois la conversion effectuée, sera alors de s'assurer que la valeur obtenue entre bel et bien dans l'intervalle de valeurs admises par ton champs (par exemple, que la valeur obtenue est bel et bien comprise entre 0 et 65535 (de tête) pour un unsigned short)
    Citation Envoyé par DarKaa Voir le message

    Une dernière réponse et je serai fixé

    Non en fait je mens J'ai juste besoin d'une dernière confirmation

    Si on prend la structure que koala01 m'a conseillé d'utiliser. J'aimerai savoir si je peux faire une liste de cette structure (std::vector, QVector, etc..) ? Car étant de taille inconnue (la structure hein) je me demande comment cela peut marcher !
    La chose importante à retenir au niveau des template, c'est que A<B> est d'un type totalement différent de A<C>, sauf si la classe template A hérite d'une classe qui n'est pas template.

    Tu peux donc, en effet, créer un std::vector<A<B>>, un autre std::vector<A<C>> et un troisième std::vector<A<D>> (ou leur équivalent QVector), mais tu ne peux pas créer un std::vector<A *> pour mettre toutes les valeurs ensembles.

    A moins, bien sur, que A n'hérite d'une classe (S) non template.

    Mais, si tu le fait, il faut savoir que tu devras créer un std::vector<S*> et que tu ne connaitra alors ta valeur que comme étant un S. Seul le polymorphisme "classique" (au sens OO du terme) pourra alors te venir en aide
    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

  12. #32
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Merci koala01 et tous les autres qui m'ont bien éclairé et accepté de me répondre.

    Je vais essayer de digérer ce que tu m'as dit koala01 et essayer d'en tirer le plus possible

    J'espère ne jamais vous revoir mais comme chacun le sait on est plus qu'on le croit confronté à des problèmes qu'il est souvent intéressant de partager. Et sur ce forum c'est très agréable de le faire

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Problème de session (encore)
    Par akapando dans le forum Langage
    Réponses: 2
    Dernier message: 23/05/2006, 16h54
  2. [xslt][Javascript] Problème de templates
    Par Dnallabar dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 03/11/2005, 11h55
  3. problème classes templates...
    Par youp_db dans le forum C++
    Réponses: 3
    Dernier message: 02/11/2005, 13h04
  4. Réponses: 3
    Dernier message: 22/03/2005, 09h13

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