J'utilise une bibliothèque tiers C ++ qui place toutes ses classes dans une espace de noms versé, appelons-le tplib_v44 code>. Ils définissent également un alias d'espace de noms générique:
error C2386: 'tplib' : a symbol with this name already exists in the current scope
5 Réponses :
On dirait qu'il y a une solution de contournement laideuse pour cela, mais pas une bonne solution.
pour ACE (avec une explication décente) et XERCES (avec un snarky" Voici comment C ++ fonctionne "Commentaire) , ils définissent des macros que vous pouvez utiliser pour le faire" génériquement ". P>
ACE_BEGIN_VERSIONED_NAMESPACE_DECL class ACE_Reactor; ACE_END_VERSIONED_NAMESPACE_DECL XERCES_CPP_NAMESPACE_BEGIN class DOMDocument; class DOMElement; XERCES_CPP_NAMESPACE_END
C'était très proche de ce qui a fini de travailler pour moi. Comme il s'est avéré, ma bibliothèque (la bibliothèque ICU) a une petite tête (uversion.h) qui - entre autres - définit l'alias d'espace de noms. Si j'inclus cet en-tête dans mon en-tête, je peux ensuite utiliser une macro d'espace de noms de noms versé, ils définissent (u_icu_namespace) dans mon fichier d'en-tête et évacuez l'espace de noms générique dans mes fichiers du CPP. Ainsi, je suis isolé des modifications apportées à l'espace de noms versé à l'encontre avec des dépendances minimales de la compilation.
er ... Ce que vous dites semble en arrière à moi. Tout le contraire, quel est le point d'essayer de déclarer votre classe en tant que membre de l'espace de noms code> tplib code>? (Oubliant pour une seconde que ce n'est même pas un espace de noms, mais plutôt un alias d'espace de noms, c'est pourquoi vous obtenez l'erreur.) P>
Il est évident que vous avez une sorte de système de contrôle de version construit sur des espaces de noms et des alias d'espace de noms. Si votre classe est introduite pour la première fois dans une "version" spécifique de l'espace de noms (comme 44) - c'est l'espace de noms qu'il doit être déclaré. Pourquoi essayez-vous de pousser votre déclaration de classe "retour dans le temps", c'est-à-dire dans Tous les em> versions passées de l'espace de noms (comme 43 et, disent, 30)? Votre classe n'existait pas dans les versions précédentes. Vous n'êtes donc pas censé le forcer là-bas. P>
Je suppose que ma question initiale n'était pas claire. L'alias d'espace de noms est fourni par le développeur tiers afin que je puisse faire référence à leurs classes comme tplib :: Someclass code>. Ils utilisent l'espace de noms versé en interne. Donc, dans leur prochaine version, l'espace de noms interne pourrait être
tplib_v50 code>. Mais je n'aurai pas à passer par tous mes fichiers et changer
tplib_v44 :: code> sur
tplib_v50 :: code> parce que j'utilise l'alias. Je ne déclare pas ma classe dans l'espace de noms; Il suffit de déclarer une classe de cette bibliothèque dans le fichier d'en-tête de mes classes. J'espère que cela a du sens.
Je pense que votre problème est dû à TPLIB étant un alias plutôt que d'un espace de noms réel
puisque la version suivante est dans une bibliothèque tierce partie, vous ne pourrez peut-être pas l'utiliser, mais à l'aide de l'espace de noms versé à l'intérieur d'un espace de noms non avancé ( Plutôt que de l'aliose) semble fonctionner pour g ++ 4.0.1 et 4.1.2. Cependant, j'ai un sentiment que cela n'est pas censé travailler ... et peut-être que d'autres problèmes ne sont pas au courant de. P>
Attention à ce que cela ne pose pas d'erreur si quelque chose code> a déjà été déclaré dans l'espace de noms versé. Il acceptera de manière silencieuse et
tplib :: quelque chose code> se référera au Versed One, ignorant
tplib :: quelque chose code>. De plus, ADL ne fonctionnera pas pour des appels avec
quelque chose code> comme argument - l'espace de noms vers la version à la version ne sera pas recherché pour les candidats.
@Johannes - cela semble raisonnable. Pouvez-vous donner un exemple de la manière dont ADL échouera dans l'utilisation de cas et non d'espace d'espace de noms direct?
Outre les problèmes mis en évidence dans les autres réponses, cela m'inquiète également un peu que vous essayez d'ajouter votre propre code à un espace de noms défini par une tierce partie en premier lieu. P>
Les espaces de noms existent pour prévenir les symboles contradictoires (classes, typdefs, Enums, etc.), en les plaçant dans leur propre espace de noms, développant ainsi un symbole unique parfaitement qualifié de ceux potentiellement qualifiés partiellement qualifiés. L'ajout de votre propre code à l'espace de noms de tiers peut causer des problèmes si (par exemple) dans une version ultérieure, ils décident qu'ils veulent aussi utiliser le même symbole (comme l'ajout de leur propre Une solution beaucoup plus sûre qui évite le problème, c'est simplement utiliser votre propre espace de noms. Appelez-le SomeclassintPlib code>) - tout d'un coup, Les espaces de noms de nom de nommage sont censés empêcher de prélever leur tête laide. C'est pourquoi il s'agit généralement d'une mauvaise pratique d'ajouter à l'espace de noms code> std code>. P>
TPLIB_EX CODE> ou quelque chose de similaire et l'association sera toujours claire, mais le conflit ne sera pas un problème et votre problème liée à un alias disparaîtra également. P>
Il n'ajoute pas de symboles à la bibliothèque, il tente de transmettre des objets déclaralisés qui existent déjà dans l'espace de noms tierces (alias).
Quel est le point? P>
vous empêcher d'ajouter des éléments supplémentaires dans leur espace de noms strong>, peut-être parce qu'ils pensent ajouter beaucoup plus de noms (et le fait qu'ils utilisent un espace de noms versé peut suggérer que). Cependant, ce ne sont que des spéculations. Cela a l'effet secondaire de prévenir les déclarations avant dans l'espace de noms que vous pensez être plus raisonnable, alors je pense que ce n'est que de mauvaises pratiques de programmation de leur côté. P>
Quelle est la meilleure façon de faire face à cela? P> BlockQuote>
Il n'y a pas de meilleure façon, mais essayez d'éviter d'utiliser des macros, les macros sont laids et pas agréables à voir (je n'aime pas tout ce genre de majuscule). Si votre préoccupation est sur "Que se passe-t-il quand ils changent de version?" (Ouais en théorie, vous devez changer "V44" en "V45" dans tout votre code) P>
Ensuite, utilisez simplement 1 en-tête unique pour transmettre tout ce dont vous avez besoin. P>
Tplibforwards.hpp strong> p>
xxx pré> S'ils changent la bibliothèque, il vous suffit d'appliquer 1 changement et dans 1 fichier. De nombreux programmeurs continuent déjà de faire avancer les déclarations en un point car c'est beaucoup plus gérable et que vous deviez transmettre de manière beaucoup de choses, vous gardez
autres en-têtes nettoyants et beaucoup plus lisibles P> #include <TpLibForwards.hpp> // my forwards declarations