C++ - namespace-alias und vorwärts-Deklaration
Ich bin mit einem C++ Drittanbieter-Bibliothek, die Orte, die alle Ihre Klassen in einem versionierten namespace, nennen wir es tplib_v44
. Außerdem definieren Sie eine generische namespace-alias:
namespace tplib = tplib_v44;
Wenn eine vorwärts-deklarieren, die ein Mitglied der Bibliothek in meiner eigenen .h-file, mithilfe der generischen namespace...
namespace tplib { class SomeClassInTpLib; }
... Bekomme ich compiler Fehler auf dem Kopf-in die third-party Bibliothek (die wird später in meine .cpp-Implementierung-Datei):
error C2386: 'tplib' : a symbol with this name already exists in the current scope
Nutzen, wenn ich die version-spezifischen namespace, dann funktioniert alles wunderbar, doch dann ... was ist der Punkt? Was ist der beste Weg, um damit umzugehen?
[BEARBEITEN] zur info für zukünftige Zuschauer, das war der ICU-Bibliothek. Eine Lösung (zumindest in meiner situation) ist in den Kommentaren zu den akzeptierten Antworten.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sieht es aus wie ein hässlicher workaround, aber keine gute Lösung.
Für ACE (mit einer anständigen Erklärung) und Xerces (mit einer snarky "dies ist, wie c++ funktioniert" Kommentar) Sie Makros definieren, die Sie verwenden können, um dies zu tun "generisch".
Sieht es aus wie ein unglücklicher c++ Artefakt, versuchen Sie die Suche in Ihrem
tplib
für diese Makros.Standard behandelt namespaces und namespace-Aliase, wie verschiedene Dinge. Du bist deklarieren
tplib
als ein namespace, so dass, wenn der compiler versucht, einen alias zuweisen später, es kann nicht beides sein, also der compiler meckert.Ich glaube, dein problem ist durch tplib ein alias, anstatt eine wirkliche namespace
Da die Versionierung in einem Drittanbieter-Bibliothek, die Sie möglicherweise nicht in der Lage, es zu benutzen, aber mit der Version Namensraum innerhalb einer nicht versionierten namespace (eher als aliasing es) scheint zu funktionieren für g++ 4.0.1 und 4.1.2 . Ich habe jedoch das Gefühl, dass dies nicht funktionieren soll ... und vielleicht gibt es einige andere Probleme, die ich bewusst bin.
Something
wurde schon erklärt in der Version Namensraum. Es wird stillschweigend akzeptieren undtplib::Something
beziehen sich auf die versionierten, ignorierentplib::Something
. Auch ADL nicht für Anrufe mitSomething
als argument - die versionierte namespace wird nicht nachgeschlagen werden für die Kandidaten.Äh..., Was Sie sagen, erscheint nach hinten zu mir. Ganz im Gegenteil, was ist der Punkt, der versucht zu erklären, Ihre Klasse als ein Mitglied der
tplib
namespace? (Vergessen für eine Sekunde, dass es nicht noch einen namespace, sondern ein namespace-alias, das ist der Grund, warum Sie den Fehler.)Es ist offensichtlich, dass Sie irgendeine Art von version-control-system baute auf die namespaces und namespace-Aliasen. Wenn Ihre Klasse wird vorgestellt in einer bestimmten "version", der den namespace (wie 44) - das ist der Namensraum muss deklariert werden. Warum sind Sie versuchen zu schieben Ihre Klasse Erklärung "back in time", d.h. in alle früheren Versionen der namespace (wie 43 und, sagen wir, 30)? Ihre Klasse nicht vorhanden in den vorherigen Versionen, so dass Sie nicht sollen, um ihn zu zwingen es.
tplib::SomeClass
. Sie sind mit der Version Namensraum intern. So in Ihre nächste Veröffentlichung, die internen namespace könntetplib_v50
. Aber das werde ich nicht müssen gehen durch alle meine Dateien, und ändern Sietplib_v44::
zutplib_v50::
da bin ich mit dem alias. Ich bin nicht deklarieren, meine Klasse in dem namespace; nur vorwärts-Deklaration einer Klasse aus dieser Bibliothek in die header-Datei von meinem Klassen. Hoffe das macht Sinn.EDIT: ich habe es darauf hingewiesen, dass ich vergessen habe den Punkt in Frage, bitte fühlen Sie sich frei, zu ignorieren!
Neben den Problemen, die wurden in den anderen Antworten, auch mich beunruhigt ein bisschen, dass Sie versuchen, fügen Sie Ihren eigenen code von einem Drittanbieter-definierten namespace in den ersten Platz.
Namespaces existieren, um zu verhindern, dass widersprüchliche Symbole (Klassen, typdefs, enums, etc.) aufeinander, indem Sie in Ihrem eigenen namespace, also die Entwicklung einer einzigartigen voll-qualifizierten symbol von potenziell identisch teilweise qualifizierte diejenigen. Indem Sie Ihre eigenen code zu Dritten namespace kann zu Problemen führen, wenn (zum Beispiel) in einer späteren version Sie sich entscheiden, Sie zu verwenden möchten, das gleiche symbol (wie das hinzufügen Ihrer eigenen
SomeClassInTpLib
) - alle von einer plötzlichen, die Benennung von Konflikten namespaces sind dazu gedacht zu verhindern, wird hinten Ihre hässlichen Kopf. Deshalb ist es in der Regel schlechte Praxis, um zu denstd
namespace.Eine viel sicherere Lösung, die vermeidet, dass das Problem ganz einfach in Ihrem eigenen Namensraum. Rufen Sie
tplib_ex
oder etwas ähnliches, und der Verein wird noch klar werden, aber der Konflikt wird nicht ein Problem sein, und Ihre alias-Problem wird auch verschwinden.Verhindern, dass Sie zusätzliche Sachen in den namespace, vielleicht weil Sie denken, dass Sie zu viel hinzufügen, weitere Namen, bald (und die Tatsache, dass Sie mit einem versionierten namespace könnte darauf hindeuten, dass). Aber diese sind nur Spekulationen. Dies hat den positiven Effekt der Verhütung forward-Deklarationen in den namespace, die Sie denken, ist mehr angemessen, so dass ich denke, es ist einfach schlechter Programmierstil auf Ihrer Seite.
Es ist nicht der beste Weg, aber versuchen zu vermeiden, mit Makros, Makros sind hässlich und nicht schön zu sehen (ich weiß nicht wie alle, dass groß-Zeug). Wenn Ihre Sorge darüber, "was passiert, wenn Sie version ändern?" (ja, in der Theorie, die Sie ändern müssen "v44" zu "v45" in allen Ihren code)
dann nur mit 1 einzigen header zu forward-deklarieren Sie alles, was Sie brauchen.
TpLibForwards.hpp
Wenn Sie ändern die Bibliothek dann müssen Sie nur anwenden 1 ändern und in 1 Datei. Viele Programmierer schon halten forward-Deklaration in einem Punkt, denn das ist viel mehr überschaubar, und im Falle Sie haben, um vorwärts zu erklären, viele Dinge, die Sie halten andere Header-Reiniger und vieles mehr lesbar.