2016-06-18 22 views
5

Namespace Mitglied nicht beilegen können in einem Namensraum definiert werden, die die Erklärung des Namensraum umschließt:Redeklaration in einem Namespace, das die ursprüngliche Erklärung

Mitglieder eines benannten Namespace kann auch außerhalb dieses Namensraum durch explizite definiert werden Qualifikation (3.4.3.2) des definierten Namens, vorausgesetzt, dass die zu definierende Entität bereits im Namensraum deklariert wurde und die Definition nach dem Punkt der Deklaration in einem Namensraum erscheint, der den Namensraum der Deklaration einschließt.

void f(); 

namespace N { void ::f() {} }  // illegal for definition 

namespace N { void ::f(); }   // what about redeclaration? 

Klasse kann in einem Namensraum definiert werden, das die Erklärung des Namensraum umschließt:

Wenn ein Klasse-Kopf-name einen verschachtelten-name-Spezifizierer enthält, wird das Klasse-specifier beziehen zu einer Klasse, die zuvor direkt in der Klasse oder dem Namespace deklariert wurde, auf die der Nested-Name-Specifier verweist, oder in einem -Element des Inline-Namespace-Satzes (7.3.1) dieses Namespace (dh nicht nur geerbt oder eingeführt von eine using-Deklaration), und der Klassenspezifizierer soll in einem Namensraum erscheinen, der die vorherige Deklaration enthält. In solchen Fällen darf der Nested-Name-Specifier des Klassenkopfnamens der Definition nicht mit einem Decltype-Specifier beginnen.

struct A; 

namespace N { struct ::A {}; }  // illegal for definition 

namespace N { struct ::A; }   // what about redeclaration? 

Auch wir haben die gleiche Regel für Funktionsdefinition und statisches Datenelement Definition.

Meine Frage ist also, ob die Deklaration (nicht Definition) legal in einem Namespace ist, der die ursprüngliche Deklaration nicht einschließt?

Antwort

1

struct ::A; anbetrifft, [dcl.type.elab]/1 macht Ihre Erklärung schlecht gebildet:

Wenn ein erarbeitet-Typ-Spezifizierer ist der einzige Bestandteil einer Erklärung, die Erklärung schlecht ausgebildet ist, es sei denn, es ist eine explizite Spezialisierung (14.7.3), eine explizite Instanziierung (14.7.2) oder es hat eine der folgenden Formen:

    Klasse-Schlüsselattribut-Spezifizierer-seq opt   Identifikator;
    friendKlasse-key :: optKennung;
    friend Klasse-Schlüssel:: opteinfach-template-ID;
    friendKlasse-Schlüssel verschachtelten-name-specifier Bezeichner ;
    friendKlasse-Schlüssel verschachtelten -name-specifier template opteinfach-template-ID;

Ich habe kein Problem in der Funktion Fall sehen; [dcl.meaning]/1 tut es erlauben:

Wenn die declarator-id qualifiziert ist, wird die Erklärung zu einem zuvor erklärt Mitglied der Klasse beziehen oder Namespace , auf die die Qualifier (oder im Falle eines bezieht sich Namespace eines Elements des Inline-Namensraumsatzes dieses Namensraums (7.3.1)) oder einer Spezialisierung davon; [...] [Hinweis: Wenn der Qualifier :: Bereichsauflösungsoperator des global ist, der declarator-id bezieht sich auf einen Namen erklärt im globalen Namespace Umfang. - Endnote]

jedoch sowohl GCC und Clang darauf bestehen, dass redeclarations, als Definitionen in einer einschließenden Namespace auftreten müssen.