2009-07-10 9 views
6

In C++ geben Sie die interne Bindung an, indem Sie Ihre Klassen- und Funktionsdefinitionen in einem anonymen Namespace einschließen. Sie können Templates auch explizit instanziieren, jedoch müssen Standards, die expliziten Instanziierungen der Templates entsprechen, im selben Namespace vorkommen. AFAICT sollten diese kompilieren, aber GCC nicht darauf:Umfasst der anonyme Namespace alle Namespaces?

namespace foo { 

template<class T> 
class bar {}; 

} 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

Mit dem Fehler:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace 'foo') 

was interessant ist, da der anonyme Namespace sollte nur Verknüpfung spezifiziert werden, nicht wirklich als Namespace funktioniert, und Der globale Namespace umschließt definitiv foo, da er jeden Namespace einschließt. Aber auch dies nicht funktioniert !:

template<class T> 
class bar {}; 

using namespace foo; 

namespace { 
template class bar<int>; 
} 

int main() 
{ 
    return 0; 
} 

Welche nicht mit dem gleichen Fehler, nur die globalen Namespace-Eintrag statt:

namespace_test.cpp:11: error: explicit instantiation of 'class bar<int>' in namespace '<unnamed>' (which does not enclose namespace '::') 

:/

+0

Welche Version von GCC - oder welche Compiler-Optionen - oder welche Plattform? Ich habe das erste Beispiel mit G ++ 4.0.1 auf MacOS X mit und ohne -Wall ausprobiert und es ohne Beanstandung oder Warnung kompiliert. –

+0

GCC 4.2 unter Solaris. –

Antwort

10

Ein anonymer Namespace ist logisch äquivalent zu

namespace _TU_specific_unique_generated_name 
{ 
    // ... 
} 
using namespace _TU_specific_unique_generated_name; 

Ein Namespace, anonym oder nicht, hat keinen Einfluss auf die Bindung ihrer Mitglieder. Insbesondere Mitglieder eines anonymen Namensraums erhalten keine magische Verbindung.

+1

Ich füge das offensichtliche hinzu, dass das Zeug in _TU_specific_unique_generated_name nicht außerhalb der Datei verwendet werden kann. – Valentein

+0

Es ist tatsächlich genau so im Standard beschrieben, akzeptiert. –

6

Ich glaube, Sie haben Ihre Antwort - anonyme Namespaces sind eindeutige, eindeutige Namespaces. Übrigens erzeugt der Compiler eine zufällige große Ganzzahl, um diesen Namespace intern darzustellen.

0

Gemäß Stroustrup (Abschnitt 8.2.5.1) hat der globale Namespace Zugriff auf den anonymen (unbenannten) Namespace, aber er sagt nicht explizit die Umkehrung.

Ich erwarte, dass Sie würden den Namespace mit einer using-Anweisung oder vollständig qualifizieren Verweise auf andere Namespaces innerhalb des unbenannte Namespace angeben müssen ...

7

Erstens: Sie sind explizit eine Klassenvorlage instanziieren, Sie sind nicht definiert, eine neue Klassenvorlage Was

sagt, ist "instanziieren Sie bitte die Klasse Vorlage bar für den Typ int hier". Sie können das nicht in einem anderen Namespace tun, genauso wenig wie Sie eine Klassenvorlage in einem anderen Namespace teilweise spezialisieren können. Insbesondere muss das Template, das explizit instanziiert werden soll, definiert sein, und in Ihrem Beispiel gibt es keinen (anonymen Namespace) :: bar <>, nur foo :: bar <>.

Zweitens: Der anonyme Namespace ist ein echter Namespace (er ist jedoch in jeder Übersetzungseinheit unterschiedlich). Es ändert auch nicht magisch Verbindung. Alles, was im Namespace {} deklariert ist, hat immer noch die Standardverknüpfung, genau wie in jedem anderen Namespace-Bereich. IIRC, es wurde sogar hinzugefügt, um Übersetzungseinheit-private, aber externe Verbindungsobjekte zu ermöglichen.

Verwandte Themen