Unterschied der Schlüsselwörter ‘typename’ und ‘class’ in Templates?

Lesezeit: 7 Minuten

Unterschied der Schlusselworter typename und class in Templates
Matte

Für Vorlagen habe ich beide Deklarationen gesehen:

template < typename T >
template < class T >

Was ist der Unterschied?

Und was genau bedeuten diese Schlüsselwörter im folgenden Beispiel (entnommen aus dem deutschen Wikipedia-Artikel über Vorlagen)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};

1646962210 856 Unterschied der Schlusselworter typename und class in Templates
Aaron Klotz

typename und class sind im Grundfall der Angabe einer Vorlage austauschbar:

template<class T>
class Foo
{
};

und

template<typename T>
class Foo
{
};

sind gleichwertig.

Allerdings gibt es bestimmte Fälle, in denen ein Unterschied besteht typename und class.

Der erste betrifft abhängige Typen. typename wird verwendet, um zu deklarieren, wenn Sie auf einen verschachtelten Typ verweisen, der von einem anderen Vorlagenparameter abhängt, z typedef in diesem Beispiel:

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

Die zweite, die Sie tatsächlich in Ihrer Frage zeigen, obwohl Sie es vielleicht nicht erkennen:

template < template < typename, typename > class Container, typename Type >

Bei Angabe von a Vorlage Vorlageder class Schlüsselwort MUSS wie oben verwendet werden – es ist nicht austauschbar mit typename in diesem Fall (Hinweis: seit C++17 sind in diesem Fall beide Schlüsselwörter erlaubt).

Sie müssen auch verwenden class beim expliziten Instanziieren einer Vorlage:

template class Foo<int>;

Ich bin mir sicher, dass es andere Fälle gibt, die ich übersehen habe, aber das Fazit ist: Diese beiden Schlüsselwörter sind nicht gleichwertig, und dies sind einige häufige Fälle, in denen Sie das eine oder andere verwenden müssen.

  • Letzteres ist so ziemlich ein Sonderfall der Tatsache, dass Sie class oder struct verwenden müssen, nicht typename, um eine Klasse zu definieren. Offensichtlich konnte keines Ihrer ersten beiden Codebits durch ersetzt werden template <typename T> typename Foo {};weil Foo definitiv eine Klasse ist.

    – Steve Jessop

    7. Januar 2010 um 23:31 Uhr


  • std::vector<int>::value_type ist kein abhängiger Typ, brauchen Sie nicht typename dort – Sie brauchen es nur, wenn ein Typ beispielsweise von einem Vorlagenparameter abhängt template<class T> struct C { typedef typename std::vector<T>::value_type type; };

    – Georg Fritzsche

    7. Januar 2010 um 23:46 Uhr


  • Und wieder, param_t ist kein abhängiger Typ. Abhängige Typen sind Namen, die von einem Vorlagenparameter abhängig sindz.B foo<param_t>::some_typenicht die Vorlagenparameter selbst.

    – Georg Fritzsche

    26. Januar 2010 um 20:22 Uhr


  • Ein C++1z-Vorschlag N4051 erlaubt Ihnen zu verwenden typenamedh template <typename> typename C.

    – Benutzer4112979

    6. Oktober 2014 um 13:57 Uhr

  • Ab GCC 5, G++ erlaubt jetzt typename in einem Template-Template-Parameter.

    – Chnossos

    8. November 2014 um 11:16 Uhr


Unterschied der Schlusselworter typename und class in Templates
Georg Fritzsche

Zum Benennen von Vorlagenparametern typename und class sind gleichwertig. §14.1.2:

Es gibt keinen semantischen Unterschied zwischen class und typename in einem Template-Parameter.

typename Es ist jedoch in einem anderen Kontext möglich, wenn Vorlagen verwendet werden – um dem Compiler anzuzeigen, dass Sie sich auf einen abhängigen Typ beziehen. §14.6.2:

Es wird davon ausgegangen, dass ein Name, der in einer Vorlagendeklaration oder -definition verwendet wird und von einem Vorlagenparameter abhängig ist, keinen Typ benennt, es sei denn, die anwendbare Namenssuche findet einen Typnamen oder der Name ist durch das Schlüsselwort typename qualifiziert.

Beispiel:

typename some_template<T>::some_type

Ohne typename Der Compiler kann im Allgemeinen nicht erkennen, ob Sie sich auf einen Typ beziehen oder nicht.

  • Ich verstehe die Regel, aber was genau hindert den Compiler daran, some_template intern als Typ zu behandeln? Entschuldigung, wenn ich etwas Offensichtliches übersehe.

    – Fledermaus

    28. März 2019 um 8:45 Uhr

  • @batbrat Hier ist die ausführliche Antwort zu diesem Thema. Z.B, some_template<T>::something * p; kann eine Zeigerdeklaration oder Multiplikation sein.

    – Alex Che

    28. September 2020 um 7:46 Uhr

  • Danke @AlexChe, ich werde den Link durchgehen!

    – Fledermaus

    28. September 2020 um 14:10 Uhr

Obwohl es keinen technischen Unterschied gibt, habe ich gesehen, dass die beiden verwendet werden, um leicht unterschiedliche Dinge zu bezeichnen.

Für eine Vorlage, die jeden Typ als T akzeptieren sollte, einschließlich eingebauter Elemente (z. B. ein Array )

template<typename T>
class Foo { ... }

Für eine Vorlage, die nur funktioniert, wenn T eine echte Klasse ist.

template<class T>
class Foo { ... }

Aber denken Sie daran, dass dies nur eine Stilsache ist, die manche Leute verwenden. Nicht vom Standard vorgeschrieben oder von Compilern erzwungen

  • Ich beschuldige Sie nicht, dass Sie es erwähnt haben, aber ich denke, dass diese Richtlinie ziemlich fehlgeleitet ist, da Programmierer sich am Ende Zeit nehmen, über etwas nachzudenken, das nicht wichtig ist (“habe ich das Richtige verwendet?”), um etwas anzuzeigen, das nicht wichtig ist t matter (“Gibt es einen eingebauten Typ, der die für diesen Vorlagenparameter erforderliche Schnittstelle implementiert?”). Wenn Mitglieder des Vorlagenparameters verwendet werden (T t; int i = t.toInt();) benötigen Sie dann eine “echte Klasse”, und Ihr Code wird nicht kompiliert, wenn Sie ihn angeben int zum T

    – Steve Jessop

    7. Januar 2010 um 23:26 Uhr

  • Wenn Sie die Verwendung auf tatsächliche Klassen beschränken möchten, sollten Sie besser eine Spezialisierung hinzufügen, um einen Fehler für Nicht-Klassentypen auszulösen/zu verursachen. Wenn Sie die Verwendung auf bestimmte Klassen beschränken möchten, spezialisieren Sie sich nur auf diese. In jedem Fall ist eine solche stilistische Unterscheidung zu subtil, um die Botschaft zu vermitteln.

    – Kartoffelklatsche

    8. Januar 2010 um 1:34 Uhr

  • Da sie dasselbe bedeuteten, verwenden Sie bitte nur eine. Ansonsten ist es wie die Verwendung von inline {, es sei denn, es ist ein Dienstag, und Sie verwenden dann next-line {.

    – Paul Tucher

    8. Oktober 2014 um 6:58 Uhr

  • +1 Ich mache das manchmal selbst … class bedeutet, dass Sie nicht nur einen “Wert” erwarten, der möglicherweise einige Operatoren unterstützt, Konstruktionen und/oder Zuweisungen kopiert oder verschiebt, sondern speziell einen Typ benötigen, der eine Semantik für den Zugriff auf Mitglieder unterstützt. Der schnellste Blick auf die Deklaration weckt dann Erwartungen und schreckt zB von der Lieferung von Einbautypen ab class Parameter, wenn das sicherlich ein Fehler wäre.

    – Toni Delroy

    7. Juli 2015 um 5:48 Uhr

  • Ich würde gerne verstehen, welche Arten von Situationen in der realen Welt existieren, in denen eine Vorlage für JEDE Klasse funktionieren würde, aber nicht mit integrierten Typen funktionieren würde. Haben Sie ein Beispiel?

    – lfalin

    23. November 2015 um 16:32 Uhr

  1. Kein Unterschied
  2. Vorlagentypparameter Container ist selbst eine Vorlage mit zwei Typparametern.

Dieses Stück Snippet stammt aus dem C++ Primer Book. Obwohl ich sicher bin, dass das falsch ist.

Jedem Typparameter muss das Schlüsselwort class oder typename vorangestellt werden:

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

Diese Schlüsselwörter haben dieselbe Bedeutung und können in einer Vorlagenparameterliste austauschbar verwendet werden. Eine Vorlagenparameterliste kann beide Schlüsselwörter verwenden:

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

Es mag intuitiver erscheinen, das Schlüsselwort typename anstelle von class zu verwenden, um einen Vorlagentypparameter zu bezeichnen. Schließlich können wir eingebaute (Nicht-Klassen-) Typen als Template-Typ-Argument verwenden. Darüber hinaus gibt typename deutlicher an, dass der folgende Name ein Typname ist. Typname wurde jedoch zu C++ hinzugefügt, nachdem Templates bereits weit verbreitet waren; Einige Programmierer verwenden weiterhin ausschließlich Klassen

1646962211 11 Unterschied der Schlusselworter typename und class in Templates
Benutzer438383

Es gibt keinen Unterschied zwischen der Verwendung <typename T> ODER <class T>; dh es ist eine Konvention, die von C++-Programmierern verwendet wird. Ich selbst bevorzuge <typename T> da es seine Verwendung klarer beschreibt; dh eine Vorlage mit einem bestimmten Typ definieren.

Hinweis: Es gibt eine Ausnahme, bei der Sie verwenden müssen class (und nicht typename) beim Deklarieren eines Template-Template-Parameters:

template <template <typename> class    T> class C { }; // valid!

template <template <typename> typename T> class C { }; // invalid!

In den meisten Fällen werden Sie keine verschachtelte Vorlagendefinition definieren, sodass beide Definitionen funktionieren werden – seien Sie einfach konsistent in Ihrer Verwendung.

989510cookie-checkUnterschied der Schlüsselwörter ‘typename’ und ‘class’ in Templates?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy