Template typedefs - Worum geht es bei Ihnen?

72

C ++ 0x verfügt über Vorlagenaliasnamen (manchmal auch als Vorlagentypedefs bezeichnet). Siehe hier . Aktuelle Spezifikation von C ++ nicht.

Was verwenden Sie gerne als Workaround? Containerobjekte oder Makros? Findest du es wert?

George Godik
quelle
3
GOTW hat sich vor einiger Zeit mit diesem Thema befasst: gotw.ca/gotw/079.htm
Assaf Lavie

Antworten:

103

Was verwenden Sie gerne als Workaround? Containerobjekte oder Makros? Findest du es wert?

Der kanonische Weg besteht darin, eine Metafunktion wie folgt zu verwenden:

template <typename T>
struct my_string_map {
    typedef std::map<std::string, T> type;
};

// Invoke:

my_string_map<int>::type my_str_int_map;

Dies wird auch in STL ( allocator::rebind<U>) und in vielen Bibliotheken einschließlich Boost verwendet. Wir verwenden es ausgiebig in einer bioinformatischen Bibliothek .

Es ist aufgebläht, aber in 99% der Fälle die beste Alternative. Die Verwendung von Makros hier ist die vielen Nachteile nicht wert.

(BEARBEITEN: Ich habe den Code geändert, um die Boost / STL-Konventionen widerzuspiegeln, auf die Daniel in seinem Kommentar hingewiesen hat.)

Konrad Rudolph
quelle
3
Wenn Sie 'Typ' anstelle von 'Typ' (oder zusätzlich zu) verwenden, funktioniert dies besser mit Boost.MPL. Was nützlich sein kann, daher denke ich, dass es eine gute Konvention ist, um zu ermutigen.
Daniel James
5
@ Zenikoder: Es ist durchaus vernünftig, es als Metafunktion zu bezeichnen, und die meisten C ++ - Metaprogrammierungsexperten tun dies (z. B. die Boost-Leute). Es gibt keine strenge Definition, aber ich persönlich nenne alles eine Metafunktion, die zur Kompilierungszeit bei bestimmten Eingaben einen Typ oder eine Kompilierungszeitkonstante ergibt. Das heißt, jede Zuordnung von einer Eingabe zu einer Ausgabe zur Kompilierungszeit. Ich weiß nicht, dass es eine vernünftigere oder allgemein akzeptierte Definition gibt. Kann ich abschließend fragen, warum Sie dieser Verwendung des Begriffs widersprechen?
Konrad Rudolph
4
@matthieu es ist eine Metafunktion, weil es einen Typ zur Kompilierungszeit berechnet
Ghita
Könnten Sie bitte eine Erklärung hinzufügen, wie eine Funktion diesen Typ zurückgeben kann?
Barracuda
@ MoKi Ich verstehe nicht was du meinst.
Konrad Rudolph
10
template <typename T>
struct my_string_map : public std::map<std::string,T> 
{
};

Sie sollten nicht von Klassen erben, die keinen virtuellen Destruktor haben. Es hängt damit zusammen, dass Destruktoren in abgeleiteten Klassen nicht aufgerufen werden, wenn sie sollten, und dass Sie möglicherweise nicht zugewiesenen Speicher haben.

Davon abgesehen könnten Sie in der obigen Instanz wahrscheinlich damit durchkommen, weil Sie Ihrem abgeleiteten Typ keine weiteren Daten hinzufügen. Beachten Sie, dass dies keine Bestätigung ist. Ich rate dir immer noch, es nicht zu tun. Die Tatsache, dass Sie es tun können, bedeutet nicht , dass Sie es sollten .

EDIT: Ja, dies ist eine Antwort auf den Beitrag von ShaChris23. Ich habe wahrscheinlich etwas verpasst, weil es über seiner / ihrer Nachricht statt unter angezeigt wurde.

xghost
quelle
3
Ist dies als Antwort auf den Beitrag von ShaChris23 gedacht?
Evan Teran
Dies sind keine Foren, Beiträge werden nicht in chronologischer Reihenfolge angezeigt. Normalerweise wäre dies ein Kommentar. Sie können nicht, also hätte vielleicht eine Community-Wiki-Antwort getan. In jedem Fall ist die Frage ziemlich alt.
GManNickG
4
Ich bemerkte, dass es ziemlich alt ist, aber ich dachte, es wäre eine gute Sache, um sicherzustellen, dass es keine falschen Praktiken fördert. ttyl
xghost
0

Manchmal können Sie einfach die nicht vorgestellten Typedefs für alle erforderlichen Typen explizit ausschreiben. Wenn die Basisklasse auf mehreren Vorlagenargumenten mit nur einem Typ erstellt wird, der typisiert werden soll, können Sie eine spezialisierte Klasse erben, wobei typedef effektiv im geerbten Klassennamen enthalten ist. Dieser Ansatz ist weniger abstrus als der Metafunktionsansatz.

Andrei Pokrovsky
quelle