2012-06-05 2 views
5

Gibt es einen besonders guten Grund, einen ausgearbeiteten Typspezifizierer zu verwenden? Unter bestimmten Umständen ist es beispielsweise erforderlich, die Schlüsselwörter template oder typename zu verwenden, um eine abhängige template oder den Typ zu disambiguieren.Wann ist ein ausgearbeiteter Typspezifizierer zu verwenden?

Aber ich kann nicht an irgendwelche Beispiele denken, wo dies für etwas wie eine Aufzählung auftreten würde. Nehmen Sie das folgende Codebeispiel:

enum Foo { A, B }; 

void bar(Foo foo); 
void baz(enum Foo foo); 

Warum kann ich wählen, um die Syntax zu verwenden baz() bietet über bar() (oder umgekehrt)? Gibt es einen mehrdeutigen Fall?

+3

Ist die Baz-Syntax nicht nur eine Verschleppung aus dem alten C-Stil, in dem Sie die Enumeration nicht typisiert hatten, so dass Sie sie explizit als enum bezeichnen mussten? Wie, wie Sie struct Foo f verwenden würden; wenn du die Struktur nicht typisiert hättest? In C++ ist das Typedef implizit in der enum/struct-Deklaration, so dass Sie nicht angeben müssen, dass der Typ eine enum/struct ist? – cppguy

+0

ähnlich ... http://stackoverflow.com/questions/742699/returning-an-enum-from-a-function-in-c –

Antwort

7

Es gibt keine Gründe, solche Spezifizierer zu verwenden, es sei denn, Sie haben es mit der Situation zu tun, wenn der Name durch eine andere "Art" verborgen ist. Zum Beispiel ist es völlig legal eine Variable zu deklarieren Foo nach der Enum Erklärung genannt, da informell gesprochen, Objektnamen und Typnamen leben in unabhängigen „Namespaces“ (siehe 3.3/4 für mehr formale Spezifikation)

enum Foo { A, B }; 

int Foo; 

Nach der int Foo Deklaration wird Ihre bar Deklaration ungültig, während die ausführlichere baz Deklaration gültig bleibt.

+0

Das macht Sinn; Ich hatte diesen Fall nicht berücksichtigt. Zugegeben, ich würde jeden schlagen, der es tut, aber ich würde gerne über diese Eckfälle wissen. Vielen Dank! (Und zu den anderen auch.) – Shirik

2

Für die Deklaration benutzerdefinierter Typen sind elaborierte Typenbezeichner erforderlich. Ein Anwendungsfall ist das Weiterleiten von Typen. Im unwahrscheinlichen Fall, dass Sie eine Funktion mit dem gleichen Namen wie ein enum Sie im Rahmen sichtbar haben Sie die ausgefeilten Typspezifizierer in der Funktionsdeklaration müssen verwenden:

enum A { A_START = 0 }; 

void A(enum A a) {} 

int main() { 
    enum A a; 
    A(a); 
} 
0

Ein Beispiel, das kommen könnte, ist, wenn Sie haben den Typ und auch ein nicht typisiertes Element mit dem gleichen Namen. die elaborierten Typspezifizierer Durch die Verwendung können Sie den Typ explizit anfordern:

struct foo {}; 
void foo(struct foo) {} 
int main() { 
    struct foo f; 
    foo(f); 
} 

Ohne den elaborierten Typspezifizierer, foo in main bezieht sich auf void foo(struct foo), nicht auf die Art struct foo. Nun, ich möchte nicht, dass das im Produktionscode steht, aber Sie haben nur nach einem Beispiel gefragt, wo es darauf ankommt. Dasselbe kann passieren, wenn der Typ und die Funktion (oder Variable) in verschiedenen Namespaces definiert sind, in denen der Nicht-Typ früher durch Nachschlagen gefunden wurde. Sie können struct durch enum oben ersetzen.

0

Ein guter Grund für die Verwendung eines ausgearbeiteten Typspezifizierers ist das Weiterleiten von Deklarationsstrukturen oder Klassen in Kopfzeilen.Bei einem Header, der den Typ

// a.h 
struct foo {}; 

definiert Sie diesen Header enthalten können Ihre Funktion

#include "a.h" 
void foo(foo *) ; 

oder verwenden Sie die ausgefeilten Art zum Prototyp:

void foo(struct foo *) ; 

oder explcitly nach vorn zu erklären mit der ausgearbeiteter Typ:

struct foo ; 
void foo(foo *) ; 

Jede der beiden letzten Möglichkeiten kann dazu beitragen, dass Ihre Header nach und nach zu einem voll vernetzten Web werden, wo jeder einzelne Header den Rest einbezieht (ich arbeite an einem Softwareprodukt, wo dies leider wahr ist und Sie zwingt, die Welt neu aufzubauen) nach vielen Arten von Änderungen, die Sie sich vorstellen könnten, wäre logisch isoliert).

Ich verstehe, dass C++ 11 auch diese Art der Vorwärtsreferenzierung für Enumerationen erlaubt, was derzeit in C++ 01-Compilern nicht erlaubt ist.