2010-09-18 5 views
5

J'ai deux programmes C++ qui doivent avoir une carte type -> int connue au moment de la compilation et égale entre les deux programmes. De plus, je voudrais m'assurer automatiquement au moment de la compilation que la carte est en tête-à-tête. Comment résoudriez-vous cela? (Les extensions C++ 0x sont autorisées). La première partie est facile: Partager untype de mappage int

template < typename T > struct map; 
template <> struct map <...> { enum { val = ...; }; }; 

entre les programmes. (La deuxième partie signifie que je ne veux pas définir accidentellement le même val pour deux types différents quelque part dans mes programmes.)

+0

Puis-je demander à quoi sert cette cartographie? – sellibitze

+0

duplication possible de [Type de conversion du métaprogramme modèle en numéro unique] (http://stackoverflow.com/questions/1708458/template-metaprogram-converting-type-to-unique-number) – kennytm

+0

La carte sera utilisée pour communiquer des données arbitraires entre un expéditeur et un programme récepteur (c'est aussi pourquoi cette question n'est pas un doublon - cela implique deux programmes qui doivent partager la même carte). – Thomas

Répondre

9

Une façon d'assurer ids uniqe est d'abuser de la fonction ami définitions

template<int N> 
struct marker_id { 
    static int const value = N; 
}; 

template<typename T> 
struct marker_type { typedef T type; }; 

template<typename T, int N> 
struct register_id : marker_id<N>, marker_type<T> { 
private: 
    friend marker_type<T> marked_id(marker_id<N>) { 
    return marker_type<T>(); 
    } 
}; 

template<typename T> 
struct map; 

template<> 
struct map<int> : register_id<int, 0> { }; 

// The following results in the following GCC error 
// x.cpp: In instantiation of 'register_id<float, 0>': 
// x.cpp:26:43: instantiated from here 
// x.cpp:14:29: error: new declaration 'marker_type<float> marked_id(marker_id<0>)' 
// x.cpp:14:29: error: ambiguates old declaration 'marker_type<int> marked_id(marker_id<0>)' 
// 
//// template<> 
//// struct map<float> : register_id<float, 0> { }; 
+0

Cool! Cela ressemble à la solution parfaite, car cela me libère de devoir spécifier tous les types dans une liste. – Thomas

+1

@Thomas maintenant il montre également les types contradictoires dans le message d'erreur. –

2

Comment utiliser boost::mpl::map? Partager quelque chose comme:

// Include your headers 

using namespace boost::mpl; 
typedef map< 
     pair<1,MyFirstClass> 
    , pair<2,MySecondClass> 
    , pair<3,MyThirdClass> 
    > m; 
1

Ils ne le font pas strictement au moment de la compilation, mais cette paire de fonctions sera automatiquement générer un identifiant unique pour chaque type passé les:

template<class T> 
int generate_type_id() { 

    static int value = 0; 
    return value++; 

} 

template<class T> 
int type_id() { 

    static int value = generate_type_id<T>(); 
    return value; 

} 

Et vous devriez être en mesure d'assurer que les deux applications partagent t il mêmes identifiants pour un type donné en invoquant explicitement les fonctions dans l'ordre dans les deux projets:

type_id<int>(); 
type_id<Foo>(); 
type_id< map<string, pair<int, Bar> >(); 

Oui, cela vous oblige à écrire une liste de tous les types impliqués, mais vous pouvez le jeter dans un en-tête, #include il entre eux, et au moins éviter la duplication du code. Cela vous absout également de devoir trouver des identifiants uniques pour chaque type par vous-même, comme le fait la réponse de Johannes Schaub, même s'il a l'avantage d'être entièrement fait à la compilation et donc vérifié statiquement par le compilateur. Je propose seulement une alternative.

+0

Cela ne fonctionne pas. Quand vous avez 'generate_type_id' modélisé par' T', il retournera toujours 0 (http://ideone.com/Ph3ha). Mais si vous en faites une fonction non modélisée, cela devrait fonctionner (http://ideone.com/zIIGb). Bien qu'il soit difficile d'assurer le même ordre. – Nobody

+0

@ Personne: Vous avez raison. Je vais mettre à jour ou supprimer à un moment donné. –

0

Une approche simple pourrait consister simplement à partager la même classe dans les deux programmes.

La réutilisation est l'un des objectifs de la POO.

Une classe qui encapsule la carte et son initialisation peut être créée puis utilisée dans les deux programmes C++.

Questions connexes