2016-01-24 6 views
9

Ich habe festgestellt, std:: Container neigen dazu, public, In-Class-Typ-Aliase (typedef/using). Z. B. Mitgliederarten unter http://en.cppreference.com/w/cpp/container/vector.Sind in C++ 1y public typedefs in der Klasse notwendig?

Wie sind sie nützlich? Sind sie nicht nur ein Relikt von Zeiten, in denen C++ keine Dinge wie auto und decltype hatte?

Bei der Implementierung eines benutzerdefinierten Containers, sollte es solche typedef s haben? Was verliere ich, wenn ich sie nicht zur Verfügung stelle?

+2

Bitte geben Sie ein konkretes * Beispiel * an, wo "Dinge wie' auto' und 'declltype'" die Aufgabe erledigen und wo zuvor ein öffentlicher 'typedef' verwendet werden musste. –

+0

Ich denke, dass diese Typen vorhanden sind, so dass die verschiedenen Typeigenschaften, die von den Algorithmen im Algorithmusheader verwendet werden, nicht explizit für jeden Containertyp instanziiert werden müssen. – StoryTeller

+0

Es hilft auch, Lesbarkeit und Wartbarkeit manchmal explizit zu sein. –

Antwort

7

Wenn Sie einen Standardbibliothek-kompatiblen Container wünschen, müssen Sie die Typedefs angeben.

Wenn Sie sich die Dokumentation ansehen, z. bei cppreference, werden Sie Passagen wie diese:

std :: vector erfüllt die Anforderungen der Container, AllocatorAwareContainer, SequenceContainer, ContiguousContainer (für T andere als bool) (da C++ 17) und ReversibleContainer.

Wenn Sie dort aufgeführten Container oder SequenceContainer oder andere Sache aussehen, werden Sie eine Liste der Anforderungen finden und die typedefs (oder eher Typen-sie nicht haben typedefs zu sein, obwohl sie oft sind) sind unter ihnen.

Wenn Sie also einen Container im Standard-Sinn des Begriffs erstellen, müssen Sie die typedefs angeben (und natürlich auch alle anderen Anforderungen erfüllen).

C++ 11 könnte theoretisch die Anforderungen lösen, hat es aber nicht. Vielleicht, weil

std::vector<int>::iterator 

ist eine verdammt viel besser lesbar als

decltype(std::declval<std::vector<int>>().begin()) 

Oder vielleicht aus einem anderen Grund.

+0

Ich denke, die Frage ist mehr über "erfüllen sie einen nützlichen Zweck" anstatt "gibt es eine formelle Anforderung, sie zu haben". Aber ja, am Ende geht es auch um formale Anforderungen. –

+0

@ Cheersandthth.-Alf Es ist, aber das hilft auch. Danke, n.m. . – PSkocik

+0

Upvoted für die Lesbarkeitsbeobachtung, aber beachten Sie, dass dies nur eine Frage der Definition * der richtigen Support-Abstraktionen * ist. In C++ 03 waren die Unterstützungsabstraktionen einfache 'typedef's oder Typdefinitionen. In C++ 11 müssen sie für neuen Code im Allgemeinen nicht: z. die Typen können durch Merkmale abgeleitet werden. –

4

Sie sind sehr nützlich im Umgang mit Meta-Programmierung, Punkt.

werfen wir einen Behälter mit Bezug zu fangen einmal, wenn es ein Behälter von POD, und ein anderes Mal, wenn es nicht:

template <class T> 
typename std::enable_if_t<std::is_pod<typename T::value_type>::value> 
doSomething(T& container){ 
    //do something 
} 

template <class T> 
typename std::enable_if_t<!std::is_pod<typename T::value_type>::value> 
doSomething(T& container){ 
    //do something 
} 

Ich habe viel von C++ für Windows zu tun, und da Windows-API bereitstellen C structs , Verwende ich viele Techniken wie diese, um zwischen echten C++ - Objekten und WinApi-Strukturen zu unterscheiden.

1

typedef (s) ermöglichen es, Implementierungen von Schnittstellen zu trennen.

Nehmen wir an, dass das C++ auto nicht definiert, wie es jetzt definiert ist und decltype im Standard nicht vorhanden war.

Aber auch jetzt, wenn Sie auto und decltype haben, ist es manchmal besser, den Typ eines Objekts explizit anzugeben. Andernfalls kann der Code schwer lesbar sein oder zu Fehlern führen.

ein einfaches Beispiel mit Typspezifizierer Betrachten auto

unsigned int x = 0; 
long y = 0; 

auto p = new auto(x + y); 

Können Sie sagen, was ist der Typ des Zeigers p?

Ist der Ausdruck *p des Typs unsigned oder signed?

Die Antwort hängt von der verwendeten Plattform ab. Der Typ von p kann entweder long * oder unsigned long * sein.

Ein ähnliches Problem existiert für Standardcontainer. Daher führt der Standard allgemeine Typnamen wie size_type ein, die garantieren, dass dieser Typ ein Typ ohne Vorzeichen ist, aber seine Breite kann je nach Plattform variieren.

Dies ermöglicht auch generischen Code zu schreiben.

In meinem Profil gibt es einen Verweis auf meinen Artikel, wo ich ein Problem zeigen, dass die Standardklasse std::bitset keinen generischen Typ size_type hat. In diesem Fall, wenn Sie zum Beispiel die Klasse std::vector<bool> zu std::bitset ersetzen müssen, müssen Sie den Code überall dort ändern, wo entweder size_type oder ein expliziter Typ wie size_t verwendet wurde.

Verwandte Themen