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

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

Langage C++ Discussion :

Un tableau de char* en paramètre template


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut Un tableau de char* en paramètre template
    Bonjour à tous,

    J'aimerais factoriser plusieurs classes de mon projet qui présentent une structure similaire.
    Voici à quoi elles ressemblent (en pseudo-code, pour être plus clair) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct access_specifier
    {
        enum type
        {
            PUBLIC,
            PROTECTED,
            PRIVATE
        };
     
        value value_;
    };
    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
     
    struct built_in_type_specifier
    {
        enum type
        {
            CHAR,
            WCHAR_T,
            BOOL,
            SHORT,
            INT,
            LONG,
            SIGNED,
            UNSIGNED,
            FLOAT,
            DOUBLE,
            VOID
        };
     
        type type_;
    };
    Afin de les factoriser, j'aimerais créer une classe template dans ce style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    template<const char** StringList>
    class string_enumeration
    {
        public:
            string_enumeration(const std::string& value);
     
            const char*
            get_value() const;
     
        private:
            static const char** string_list_; //on aura string_list_ = StringList
            int value_index_; //index dans le tableau de char*
    };
    Pour avoir un équivalent de access_specifier, on fera ceci (enfin, on aimerais bien faire ceci, justement ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    const char* access_specifier_string_list[] = {"public", "protected", "private", ""};
     
    typedef string_enumeration<access_specifier_string_list> access_specifier;
    Ainsi, on créera un access_specifier de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    access_specifier an_access_specifier("public");
    Si "public" ne fait pas partie de la liste de char*, on balancera une exception ou un assert… mais là n'est pas le problème. La classe va mémoriser l'index de la chaîne reçue (ici 0, puisque "public" est le premier élément de la liste de char*).
    L'appel à get_value() n'a plus qu'à renvoyer un pointeur vers la chaîne pointée par l'index.

    Le code semble se construire correctement, mais aucun binaire n'est linké. Lorsque j'essaie de construire une deuxième fois, gcc se résout à me tenir ce charmant discours :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/qualified_identifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    make[2]: quittant le répertoire « /mnt/data/Développement/Socoa »
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    make[1]: quittant le répertoire « /mnt/data/Développement/Socoa »
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/member_declarator_bit_field_member.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/qualified_operator_function_id.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/direct_declarator_function_part.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/namespace_definition.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/cv_qualifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/identifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/member_declaration_member_declarator_list.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/qualified_nested_id.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/member_declaration_unqualified_id.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/function_definition.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/string_enumeration.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/class_specifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/qualified_template_id.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/nested_name_specifier_template_id_part.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/simple_declaration.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/simple_template_type_specifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/template_declaration.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/template_id.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/nested_identifier_or_template_id.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/member_declarator_declarator.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/direct_declarator_array_part.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/member_specification_access_specifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/member_declaration_function_definition.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/using_declaration.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree/built_in_type_specifier.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    CMakeFiles/socoa.dir/src/socoa/cpp/program_syntax_tree_to_string_converter.cpp.o:(.data.rel.local+0x0): multiple definition of `socoa::cpp::program_syntax_tree::access_specifier_string_list'
    CMakeFiles/socoa.dir/src/socoa/cpp/declaration_syntax_analyzer.cpp.o:(.data.rel.local+0x0): first defined here
    collect2: ld returned 1 exit status
    make[2]: *** [lib/Debug/libsocoa.so] Erreur 1
    make[1]: *** [CMakeFiles/socoa.dir/all] Erreur 2
    make: *** [all] Erreur 2
    Process terminated with status 2 (0 minutes, 10 seconds)
    0 errors, 0 warnings

    Dois-je m'en tenir à du polymorphisme dynamique pour effectuer cette factorisation ?
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  2. #2
    Membre expérimenté Avatar de Nogane
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    241
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 241
    Par défaut
    Bonjours,
    Non ça ne peu pas marcher car dans:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typedef string_enumeration<access_specifier_string_list> access_specifier;
    Il faut que access_specifier_string_list soit une expression constante. Un pointeur ne peut pas en être une car il sera initialisé a l'exécution.
    (Je ne suis pas sur sur alors arrêtez moi qui je dit des bêtises)

    Sans y avoir trop reflechit, je dirait que tu va devoir initialiser ta class string_enumeration a l'execution. Elle ne sera donc plus template.
    Pas besoin du polymorphisme si tu crée une fonction(design pattern Factory) qui te crée et remplit ton string_enumeration en fonction du type que tu lui demande.

    EDIT: Peut-etre que dans ce cas un vector<string> suffirait?

  3. #3
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Citation Envoyé par Nogane Voir le message
    Un pointeur ne peut pas être une [expression constante] car il sera initialisé a l'exécution.
    Je ne pense pas, une adresse étant une valeur constante comme une autre.

    Citation Envoyé par Nogane Voir le message
    EDIT: Peut-etre que dans ce cas un vector<string> suffirait?
    J'ai fait mon premier essai avec un vector de string (je n'utilise les types à la C qu'en cas de force majeur). Malheureusement, GCC m'a jeté avec un simple "vector<string> ne peut pas être un paramètre template", ce qui est normal puisqu'on ne peut pas initialiser un vector à la compilation.
    J'espère que ce ne sera pas le cas avec les std::initialization_list, parce que je compte pas mal sur C++0x pour simplifier ce genre de galère.

    Bon, je retrouve un peu la raison en déplaçant la définition dans un .cpp comme il se doit.
    Le .h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    const char** access_specifier_string_list;
     
    typedef string_enumeration<access_specifier_string_list> access_specifier;
    Le .cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    access_specifier_string_list = {"public", "protected", "private", ""};
    Évidemment, ça ne compile pas puisque access_specifier_string_list n'est pas constant. J'ai juste copié ce code pour la pédagogie.


    Maintenant, j'ai essayé de rajouter un niveau de pointeur :
    Le .h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    const char** access_specifier_string_list_var;
    const char*** const access_specifier_string_list = &access_specifier_string_list_var;
     
    typedef string_enumeration<access_specifier_string_list> access_specifier;
    Le .cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    access_specifier_string_list_var = {"public", "protected", "private", ""};
    Mais maintenant le monsieur me dit que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    /mnt/data/Développement/Socoa/src/socoa/cpp/program_syntax_tree/access_specifier.h:33: error: ‘socoa::cpp::program_syntax_tree::access_specifier_string_list’ cannot appear in a constant-expression
    /mnt/data/Développement/Socoa/src/socoa/cpp/program_syntax_tree/access_specifier.h:33: error: template argument 1 is invalid
    /mnt/data/Développement/Socoa/src/socoa/cpp/program_syntax_tree/access_specifier.h:33: error: invalid type in declaration before ‘;’ token
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

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

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Un paramètre template est soit un type (lui-même template ou non) soit une expression connue à la compilation. Ce n'est pas ton cas, donc il va falloir contourner le "problème".

  5. #5
    Membre chevronné
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Par défaut
    Justement, conceptuellement parlant, l'ensemble {"public", "protected", "private"} est connu à la compilation… pourquoi n'est-ce pas le cas en pratique ?

    Par ailleurs, je suis en train de compiler la svn de gcc 4.4 pour voir si std::initialization_list passerait.
    http://gcc.gnu.org/projects/cxx0x.html
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

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

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Tu peux passer un char, mais pas une séquence de char. C'est une conséquence des règles de la norme

    EDIT : à moins de faire MonTemplate<'a', 'b', 'c'>

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 20
    Dernier message: 20/03/2013, 07h32
  2. problème dllImport avec tableau de char[] en paramètre E/S
    Par moulefrite dans le forum Windows Forms
    Réponses: 4
    Dernier message: 24/12/2008, 10h07
  3. Ansistring et tableau de char
    Par rabbi_jaccob dans le forum C++Builder
    Réponses: 2
    Dernier message: 24/12/2004, 11h51
  4. Adresse d'un tableau de char
    Par Trap D dans le forum C
    Réponses: 8
    Dernier message: 23/12/2003, 12h02
  5. Réponses: 4
    Dernier message: 10/10/2003, 18h04

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