2013-02-27 5 views
10

Ich habe den C++ 11-Standard (na ja, der n3242-Entwurf) und das Internet durchforstet, konnte aber keine genaue Antwort finden. Der folgende Code wird mit clang 3.2 und g ++ 4.7.2 sowie mit Visual Studio 2010 korrekt kompiliert, aber ich würde stattdessen einen Fehler erwarten.typedef und die Verwendung der Deklaration für den gleichen Namen bei gleichem Gültigkeitsbereich

#include <iostream> 
#include <typeinfo> 


typedef int a_t; 


namespace a_ns 
{ 
class a_t {}; 
} 


using a_ns::a_t; 


int main() 
{ 
    a_t a; 
    std::cout << typeid(a).name() << std::endl; 
    return 0; 
} 

Built mit:

clang -std=c++11 -pedantic -Wall -o a a.cpp -lstdc++ 
g++ -std=c++11 -pedantic -Wall -o a a.cpp -lstdc++ 
cl -EHsc -GR a.cpp 

Klappern und g ++ Executables print "i" erzeugt, die, daß die a des Typs int anzuzeigen scheint, ist, und die typedef vorherrschte. cl generierte ausführbare Ausdrucke "Klasse a_ns :: a_t", die darauf hinweisen, dass Visual Studio die using-Deklaration mehr mochte.

Ich würde erwarten, dass der Code nicht nach den folgenden Standardauszügen kompilieren. Ich würde einen Fehler erwarten, der dem "Ziel der Verwendung von Deklarationskonflikten mit einer bereits vorhandenen Deklaration" ähnelt.

7.1.3.6 Similarly, in a given scope, a class or enumeration shall not be declared with the same name as a typedef-name that is declared in that scope and refers to a type other than the class or enumeration itself.

7.3.3.1 A using-declaration introduces a name into the declarative region in which the using-declaration appears.

7.3.3.2 Every using-declaration is a declaration [...]

Es ist wahrscheinlich etwas, was ich in der Norm fehlte, die dieses Verhalten erklärt (oder ich bin einfach zu müde, das Offensichtliche zu sehen), aber ich kann nicht scheinen, um es zu finden.

Vielen Dank.

Antwort

4

Das stimmt, und was Sie gezeigt haben, macht den Code ungültig. Es gibt auch 3.3.1p4, wodurch es ungültig wird (siehe 7.3.3p13).

Für einen Realitätstest habe ich mit ICC getestet und es lehnt es wie erwartet ab.

+0

Wenn der Hauptteil von 'main()' leer wäre, wäre dieses Programm auch ungültig? In Absatz 7.1.3/6 heißt es: "In einem bestimmten Umfang darf ein typedef-Spezifizierer nicht dazu verwendet werden, ** den Namen eines in diesem Geltungsbereich deklarierten Typs neu zu definieren, um auf einen anderen Typ zu verweisen. * [Beispiel:' class complex {/ ... /}; typedef int complex; // Fehler: redefinition' -end Beispiel *] "*. In der Frage definiert "typedef" den Namen nicht "neu". Wenn sie nach der 'using' Deklaration verschoben werden, geben alle Compiler einen Fehler aus. –

+0

@andy Wenn Main leer ist, wäre es auch ungültig, nach den Zitaten, die wir gefunden haben. ob ein anderes Zitat auch zutrifft, ist dann irrelevant. normalerweise findet eine Neudefinition eines Namens für 'Klasse A {} statt; typedef AA; '(zuerst ist es nur ein Klassenname. dann ist es auch ein typedef-name. Der Name wird neu definiert, weil hinterher immer noch nur ein einziger Name existiert, aber er hat beide syntaktische Attribute. Das ist anders als der C-Modell). –

+0

OK, danke für die Klärung! +1 –

Verwandte Themen