statische Globale und anonyme Namespaces in C ++

11
  1. Warum hat C ++ bei der Einführung des letzteren zwischen statischen Globals (interne Verknüpfung) und Symbolen in einem unbenannten Namespace (externe Verknüpfung, aber keine Möglichkeit, von außen darauf zu verweisen) unterschieden?

  2. Sind diese Gründe noch gültig oder gibt es neue?

  3. Gibt es noch Orte, an denen sie sich noch unterscheiden, außer der willkürlichen Regel, dass anonyme globale Gewerkschaften (oder Namespace-Gewerkschaften) sein müssenstatic , und was sind sie?

  4. Wenn es für Bonuspunkte keine guten Gründe mehr gibt, sich zu unterscheiden, gibt es eine Aufforderung, sie gleichwertig zu machen?


Als C ++ Namespaces (C ++ 98) und speziell unbenannte Namespaces einführte, wurden statische Globals in einem Anfall von Begeisterung als veraltet und schlechter als das Neue eingestuft, obwohl dies mit C ++ 11 rückgängig gemacht wurde :
Verachtung des statischen Schlüsselworts… nicht mehr?

Vor C ++ 11 konnten Symbole mit interner Verknüpfung nicht als Vorlagenargumente verwendet werden: Warum erforderte C ++ 03 Vorlagenparameter für eine externe Verknüpfung?

Deduplikator
quelle
Es sieht so aus, als hätten Sie meistens Ihre eigene Frage beantwortet, mit Ausnahme des Bits "Konforme Implementierung". Vielleicht sollten Sie die zweite Hälfte entfernen und stattdessen als Antwort veröffentlichen? Oder bleibt hier noch etwas unbeantwortet?
Kyle Strand
@ KyleStrand hat alles neu formuliert.
Deduplikator

Antworten:

3

Ich nehme an, dies beantwortet nicht alle Ihre Fragen (oder eine davon?), Aber der Hauptunterschied zwischen statischen Deklarationen auf Dateiebene und anonymen Namespaces besteht darin, dass die Namespaces auch für Typen gelten (Sie können keinen staticTyp in der deklarieren In dem gleichen Sinne, in dem Sie eine Variable deklarieren, wird der Namespace bevorzugt. Daher gibt es eine einzige Redewendung zum Deklarieren von Daten und Typen mit Dateibereich.

Beispielhaft sollte der folgende Code gut kompiliert werden. (Nicht wirklich nützlich, da man nicht zwischen beiden Typen unterscheiden kann, aber erlaubt)

#include <iostream>

struct Foobar
{
    int   foo;
    float bar;
};

namespace
{

struct Foobar
{
    double baz;
};

} // namespace

int main()
{
    std::cout << "HELLO!\n";
}

Ein Live-Test hier .

glampert
quelle
Es wird kompiliert, weil Sie Foobar nicht in der Hauptfunktion verwenden.
dshil
Noch wichtiger ist, was passiert, wenn eine andere CPP-Datei ihre eigene Version von deklariert struct Foobar? Schlimmer noch, nehmen wir an, es ist jetzt class Foobar. Überlegen Sie, wie Sie Konstruktoren für beide erstellen möchten.
Dgnuff