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 ?