Nutzung von using namespace std;



  • Es geht nicht nur um Performance, sondern auch um das Thema UB. Ich habe die aktuelle Norm noch nicht durchgelesen, aber in C++17 bestand das Problem, dass die Richtlinie für die Containerentwicklung (d.h. alle Container in der Norm sind betroffen) vorsehen, dass swap O(1) ist, und das für viele Allokatoren nicht erfüllt werden kann. Man muss bei swap std::allocator_traits<Allocator<T>>::is_always_equal und std::allocator_traits<Allocator<T>>::propagate_on_container_swap berücksichtigen, ist nicht mindestens eines der beiden std::true_type, dann liefert std::swap UB.



  • Mmh, verstehe ich nicht. Es geht doch darum die Spezialisierung zu finden. Wird diese nicht gefunden, wird "normal" geswappt. Warum sollte das UB sein, selbst wenn es O(n^99) wäre?



  • Nö, dank Intellisense und Snippets spart man ja nicht mal mehr Tipparbeit. Also lieber eindeutig bleiben und Probleme vermeiden.



  • @Jockelx sagte in Nutzung von using namespace std;:

    Mmh, verstehe ich nicht. Es geht doch darum die Spezialisierung zu finden. Wird diese nicht gefunden, wird "normal" geswappt. Warum sollte das UB sein, selbst wenn es O(n^99) wäre?

    Wenn man immer std::swap schreibt, wird die Spezialisierung nicht gefunden und std::swap genutzt. std::swap hat aber das Problem, dass es einige zusätzliche Annahmen macht, die seit C++11 nicht mehr generell erfüllt sind. Ich habe einen eigenen Beitrag dazu eingefügt, damit dürfte nachvollziehbar sein was ich meine.


  • Gesperrt

    Danke für den Tipp auch!



  • @john-0 sagte in Nutzung von using namespace std;

    Wenn man immer std::swap schreibt, wird die Spezialisierung nicht gefunden und std::swap genutzt. std::swap hat aber das Problem, dass es einige zusätzliche Annahmen macht, die seit C++11 nicht mehr generell erfüllt sind. Ich habe einen eigenen Beitrag dazu eingefügt, damit dürfte nachvollziehbar sein was ich meine.

    Nicht, wenn man seine Spezialisierung im Namespace std implementiert:

    struct MyStruct
    {
    };
    
    namespace std
    {
        template<>
        void swap( MyStruct& lhs, MyStruct& rhs )
        {
           ...
        }
    }
    


  • @DocShoe sagte in Nutzung von using namespace std;:

    Nicht, wenn man seine Spezialisierung im Namespace std implementiert:

    Aua, das ist ein absolutes No-go.



  • @john-0
    Nö, das ist vom Kommittee sogar explizit erlaubt worden. Man spezialisiert seine swap Funktion im std-namespace. Man muss seine swap-Funktion aber als Spezialisierung implementieren, nicht als Überladung. Bis C++20 jedenfalls.

    Edit:
    Referenz siehe Box "Specializations"



  • @DocShoe sagte in Nutzung von using namespace std;:

    @john-0
    Nö, das ist vom Kommittee sogar explizit erlaubt worden. Man spezialisiert seine swap Funktion im std-namespace. Man muss seine swap-Funktion aber als Spezialisierung implementieren, nicht als Überladung. Bis C++20 jedenfalls.

    Ok, wieder was gelernt. Wobei ich mich nicht ganz falsch erinnere, denn da steht ja.

    std::swap may be specialized in namespace std for program-defined types, but such specializations are not found by ADL (the namespace std is not the associated namespace for the program-defined type).

    D.h. es ist zwar möglich bis C++20 ist es aber nicht sinnvoll, weil es ggf. nicht gefunden wird.


  • Mod

    Im Gegensatz zur hier oft apodiktisch vertretenen Meinung, dass ein globales using namespace std; universell schwachsinnig ist und nur von Anfängern und Juergen Wolf eingesetzt wird, habe ich in professionellem Umfeld zu schätzen gelernt, dass selbst in riesigen Projekten std in zentralen Headern geöffnet wird. Es ist in der Praxis wirklich einfach unproblematisch. Ich würde es definitiv nicht in einer Bibliothek machen, da man ja nicht seine Idiome auf den User zwingen will, aber in einem eigenen Projekt ist es kein Thema.



  • @Columbo sagte in Nutzung von using namespace std;:

    Im Gegensatz zur hier oft apodiktisch vertretenen Meinung, dass ein globales using namespace std; universell schwachsinnig ist und nur von Anfängern und Juergen Wolf eingesetzt wird, habe ich in professionellem Umfeld zu schätzen gelernt, dass selbst in riesigen Projekten std in zentralen Headern geöffnet wird. Es ist in der Praxis wirklich einfach unproblematisch. Ich würde es definitiv nicht in einer Bibliothek machen, da man ja nicht seine Idiome auf den User zwingen will, aber in einem eigenen Projekt ist es kein Thema.

    Tja nö, es ist eben nicht generell unproblematisch. Bekanntestes Beispiel: max unter Windows.



  • Ich mache es nie global, aber durchaus lokal, wenn ich in einer Methode häufiger Dinge aus einem anderen Namespace verwende. Nicht unbedingt mit std, weil es nicht soviel tipparbeit ist, aber wenn die namespaces länger sind, nehme ich gern mal using namespace.


  • Mod

    @Tyrdal sagte in Nutzung von using namespace std;:

    @Columbo sagte in Nutzung von using namespace std;:

    Im Gegensatz zur hier oft apodiktisch vertretenen Meinung, dass ein globales using namespace std; universell schwachsinnig ist und nur von Anfängern und Juergen Wolf eingesetzt wird, habe ich in professionellem Umfeld zu schätzen gelernt, dass selbst in riesigen Projekten std in zentralen Headern geöffnet wird. Es ist in der Praxis wirklich einfach unproblematisch. Ich würde es definitiv nicht in einer Bibliothek machen, da man ja nicht seine Idiome auf den User zwingen will, aber in einem eigenen Projekt ist es kein Thema.

    Tja nö, es ist eben nicht generell unproblematisch. Bekanntestes Beispiel: max unter Windows.

    Ich verstehe gar nicht, was Dein Argument sein soll. std::max wird gerade nicht funktionieren weil max ein Makro ist. NOMINMAX ist quasi obligatorisch. Haetten sie max als Funktion deklariert, dann wäre using namespace std; kein Problem, weil die STL Version als Funktionstemplate per overload resolution korrekt differenziert werden wuerde.



  • @Columbo
    Naja das Problem ist...
    Mit using namespace std; funktioniert max(). Wenn man dann zusätzlich Windows.h ohne NOMINMAX reinholt ... dann funktioniert das in den meisten Fällen immer noch. Nur nicht gleich, weil dann das zurückgegebene Argument mehrmals ausgewertet wird. Und der Typ des Ausdrucks ist denke ich auch anders.

    Ohne using namespace std; muss man std::max schreiben. Und da bekommt man mit Windows.h (ohne NOMINMAX) dann wenigstens einen Fehler beim kompilieren.


  • Mod

    @hustbaer Ich habe postuliert "Namespaces ausschütten ist böse in Libs, aber ok in eigenen Projekten".

    WinAPI schiesst voll daneben indem es Makros mit extrem simplen und oft verwendeten Namen definiert. Das ist doof, und die wichtigste Schlussfolgerung ist, dass der Entwickler unbedingt NOMINMAX definieren muss—using namespace hin oder her, min/max als Makros ist purer Zirkus. using namespace std; ist da nebensächlich.



  • @Columbo
    Bezüglich using namespace std; in eigenen (non-Library) Projekten... also "OK" ist es schon, ich würde es aber nicht unbedingt haben wollen. Kommt wahrscheinlich drauf an was man gewohnt ist und auch wie man seine lokalen Bezeichner benennt.

    Was den Rest angeht: Klar, sehe ich auch so. Ich wollte nur erklären wie using namespace std; in Kombination mit Windows.h zu einem Problem führen kann.



  • Abgesehen von den Problemen mit using namespace, finde ich es subjektiv mittlerweile tatsächlich besser, wenn z.B. std::string oder std::vector dransteht, und nicht einfach nur string oder vector. Das ist irgendwie viel griffiger und eindeutiger.



  • Geht mir genau so. Wobei ich das nie anders kannte und mir daher auch vorstellen kann dass man sich auch an einfach nur string und vector gewöhnen kann.


Anmelden zum Antworten