Namensräume: "Rücksprung" in Namensraum einer speziellen Bibliothek



  • Hallo,

    ich verwende die Boost-Bibliothek (u. a. für Serialisierung und Operationen auf Dateien und Pfaden) und habe ein Problem bei der Definition eigener Namensräume. Wenn ich z. B. eine Verschachtelung von Namensräumen habe, wie kann ich dann wieder auf die boost-Funktionen zugreifen? Bei STL-Konstrukten funktioniert der Zugriff auf den globalen Namensraum ja z. B. einfach per "::std::string", aber bei boost klappt es weder per "::boost::..." noch per "boost::...".

    Jedenfalls kommen beim Kompilieren hunderte Warnungen und Fehler, die einzig und alleine mit diesen Namensräumen in Zusammenhang mit boost zu tun haben, denn vor deren Einführung lief alles perfekt. Ich brauche sie jedoch zur besseren Strukturierung und Übersicht.

    Am einfachsten lässt es sich wie immer an einem Beispiel erklären:

    // Header-Datei
    ...
    #include <boost/serialization/map.hpp>
    #include <boost/filesystem/operations.hpp>
    #include <boost/filesystem/path.hpp>
    #include <string>
    ...
    
    namespace ns1 {
    namespace ns2 {
    
    class Klasse {
      private:
        boost::filesystem::path pfad; // Wie müsste der korrekte Zugriff lauten?
        ::std::string bla;
      public
        void doSomething();
    };
    
    }}
    
    // Implementierungsdatei
    namespace ns1 {
    namespace ns2 {
     void Klasse::doSomething() {
     }
    }}
    
    // Anwendungsdatei
    #include "Klasse.h"
    
    using ns1::ns2::Klasse;
    
    int main() {
     Klasse k;
     k.doSomething();
     return 0;
    }
    

    In den Warnungen/Fehlern sehe ich überall Dinge wie "ns1::ns2::boost::...". Meien Frage lautet daher: Wie kann ich dem Compiler verklickern, dass der boost-Namensraum außerhalb der Namensräume ns1 und ns2 existiert?



  • boost::filesystem::path pfad

    Das ist so schon richtig.

    Meien Frage lautet daher: Wie kann ich dem Compiler verklickern, dass der boost-Namensraum außerhalb der Namensräume ns1 und ns2 existiert?

    Warum ausserhalb? Du brauchst es ja lediglich in der Klasse. 🙄



  • Ok, aber wenn ich innerhalb der Klasse darauf per "boost::..." zugreife, hagelt es die Fehler und Warnungen. Muss ich sonst etwas beachten?


  • Administrator

    Es wäre vielleicht sinnvoll, wenn du uns sagen würdest, was für Fehler es hagelt. Denn man benutzt es genau so.

    Grüssli



  • TheBrain schrieb:

    Ok, aber wenn ich innerhalb der Klasse darauf per "boost::..." zugreife, hagelt es die Fehler und Warnungen. Muss ich sonst etwas beachten?

    Richtig includen und das ist es gewesen. 🙄



  • Und wieso muss ich dann bei STL-Konstrukten "::std::..." verwenden? Es treten wirklich hunderte, wenn nicht tausende Warnungen/Fehler auf, hauptsächlich werden dabei irgend welche boost-Dateien erwähnt. Aussagen tun die ganzen Dinger allerdings nichts. Ich vermute, die sind alle auf die Namensräume zurückzuführen.



  • TheBrain schrieb:

    Und wieso muss ich dann bei STL-Konstrukten "::std::..." verwenden? Es treten wirklich hunderte, wenn nicht tausende Warnungen/Fehler auf, hauptsächlich werden dabei irgend welche boost-Dateien erwähnt. Aussagen tun die ganzen Dinger allerdings nichts. Ich vermute, die sind alle auf die Namensräume zurückzuführen.

    Musst du doch gar nicht, nur wenn zwischen :: und dem aktuellen Namensraum noch ein std-Namensraum stehen würde.



  • Also, bin noch mal "rüber" ins Linux, hier ein paar Fehlermeldungstypen:

    "Fehler: BlaBlupp wurde in diesem Gültigkeitsbereich nicht definiert"
    "Fehler: Basisoperand von »->« hat Nicht-Zeiger-Typ »ns1::ns2::boost::filesystem::directory_iterator«"
    "Fehler: »cerr« ist kein Element von »ns1::ns2::std«
    

    Und dann noch unzählige daraus resultierende Fehler wie

    "/usr/include/c++/4.2/bits/fstream.tcc:50: Fehler: invalid use of incomplete type »class ns1::ns2::std::basic_filebuf<_CharT, _Traits>«"
    

    Gibt es irgend etwas, was ich bei der verwendung eigener Namensräume sonst noch beachte muss? Wie sieht es mit using-Direktiven aus? Wenn ich z. B. eine weitere Klasse im Namensraum ns1::ns2 erstelle und darin eine andere Klasse des gleichen Namensraums verwende, kann/muss ich diese dann jedes Mal z. B. per ns1::ns2::Klasse verwenden oder kann ich per "using ns1::ns2::Klasse;" die Schreibweise abkürzen oder muss ich gar keinen Namensraum angeben?



  • Du inkludierst die Header nicht zufällig innerhalb deines Namensraums?



  • Tippgeber schrieb:

    Du inkludierst die Header nicht zufällig innerhalb deines Namensraums?

    Natürlich tut er das, das hat ja drakon auch vermutlich gemeint.



  • hustbaer schrieb:

    Tippgeber schrieb:

    Du inkludierst die Header nicht zufällig innerhalb deines Namensraums?

    Natürlich tut er das, das hat ja drakon auch vermutlich gemeint.

    Nein. Die Reihenfolge, die ich verwende, ist folgende:

    #ifndef HEADER_H // entfällt natürlich bei Implementierungsdateien
    #define HEADER_H // "
    
    #include ...
    #include ...
    
    using ...
    using ...
    
    ns1 {
     ns2 {
      class Klasse {
      ...
      };
     }
    }
    
    #endif // entfällt natürlich bei Implementierungsdateien
    

    Ist diese Reihenfolge so grundsätzlich in Ordnung?

    Zu meiner Schande muss ich gestehen, dass ich doch tatsächlich in einer der Header-Dateien eine schließende geschweifte Klammer vergessen habe, die den äußeren Namensraum wieder schließt. Ich entschuldige mich dafür in aller Form bei euch! Da hätten wir noch lange suchen können ...

    Herzlichen Dank für eure Hilfe!



  • Ja die Reihenfolge ist OK.

    Was nicht so toll ist ist das using in Header-Files.

    Und wenn schon unbedingt, dann eher in deinem Namespace und nicht gleich im global namespace.

    Also eher so (doch wieder andere Reihenfolge):

    #ifndef HEADER_H
    #define HEADER_H
    
    #include ...
    #include ...
    
    ns1 {
     ns2 {
    
      using ... // weglassen wenn nicht unbedingt nötig
      using ... // weglassen wenn nicht unbedingt nötig
    
      class Klasse {
      ...
      };
     }
    }
    
    #endif
    

    In den .cpp Files kannst du das using im Prinzip hinschreiben wo du magst, das gilt dann ja immer nur für das eine File, ist dann nicht weiter schlimm.

    Zu meiner Schande muss ich gestehen, dass ich doch tatsächlich in einer der Header-Dateien eine schließende geschweifte Klammer vergessen habe

    Und damit hattest du ein include innerhalb eines Namespace stehen 😉
    Wenn auch ohne es zu merken oder beabsichtigt zu haben.



  • hustbaer schrieb:

    In den .cpp Files kannst du das using im Prinzip hinschreiben wo du magst, das gilt dann ja immer nur für das eine File, ist dann nicht weiter schlimm.

    Einspruch bzw. Einschränkung: Überall nach den Includes :).

    Sonst haben diese nämlich auch schon was von der Namespace Pollution.



  • @LordJaxom: ja. gut. korrekt.
    Natürlich sollte man includes allerdings auch immer so schreiben dass es wurscht ist wie verschmutzt der globale Namespace ist. Tut zwar vermutlich kaum jemand, aber das ist wieder was anderes 🙂


Anmelden zum Antworten