c++ - Unterschied der Schlüsselwörter 'Typname' und 'Klasse' in Vorlagen?


Für Vorlagen habe ich beide Deklarationen gesehen:

template < typename T >
template < class T >

Was ist der Unterschied?

Und was genau bedeuten diese Keywords im folgenden Beispiel (aus dem Wikipedia-Artikel über Templates)?

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


Answers



typename und class sind im grundlegenden Fall der Angabe einer Vorlage austauschbar:

template<class T>
class Foo
{
};

und

template<typename T>
class Foo
{
};

sind gleichwertig.

typename gibt es spezielle Fälle, in denen ein Unterschied zwischen typename und class .

Der erste ist bei abhängigen Typen. typename wird verwendet, um zu deklarieren, wenn Sie auf einen geschachtelten Typ verweisen, der von einem anderen Template-Parameter abhängt, wie z. B. typedef in diesem Beispiel:

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

Das zweite, das Sie tatsächlich in Ihrer Frage zeigen, obwohl Sie es vielleicht nicht bemerken:

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

Bei der Angabe einer Template-Vorlage MUSS das class Schlüsselwort wie oben verwendet werden - es ist in diesem Fall nicht mit typename austauschbar (Hinweis: Seit C ++ 17 sind in diesem Fall beide Schlüsselwörter erlaubt) .

Sie müssen auch eine class wenn Sie eine Vorlage explizit instanziieren:

template class Foo<int>;

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




Für die Benennung von Vorlagenparametern sind typename und class äquivalent. §14.1.2:

Es gibt keinen semantischen Unterschied zwischen Klasse und Typname in einem Template-Parameter.

typename ist jedoch in einem anderen Kontext möglich, wenn Sie Vorlagen verwenden - um den Compiler darauf typename dass Sie sich auf einen abhängigen Typ beziehen. §14.6.2:

Ein Name, der in einer Template-Deklaration oder -Definition verwendet wird und von einem Template-Parameter abhängig ist, wird nicht als Typ deklariert, es sei denn, die anwendbare Namenssuche findet einen Typnamen oder der Name wird durch das Schlüsselwort Typname qualifiziert.

Beispiel:

typename some_template<T>::some_type

Ohne typename der Compiler im Allgemeinen nicht sagen, ob Sie sich auf einen Typ beziehen oder nicht.




Während es keinen technischen Unterschied gibt, habe ich die beiden verwendet, um etwas andere Dinge zu bezeichnen.

Für eine Vorlage, die einen beliebigen Typ als T akzeptieren soll, einschließlich integrierter Elemente (z. B. ein Array)

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

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

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

Aber denken Sie daran, dass dies eine reine Stilart ist, die manche Leute benutzen. Nicht vom Standard vorgeschrieben oder von Compilern erzwungen




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



Dieser Ausschnitt stammt aus einem C ++ Primer-Buch. Obwohl ich mir sicher bin, ist das falsch.

Jedem Typparameter muss die Schlüsselwortklasse oder der Typname 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 die gleiche Bedeutung und können innerhalb 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 Typname statt Klasse zu verwenden, um einen Vorlagentypparameter zu bestimmen. Schließlich können wir integrierte (Nichtklassen-) Typen als Vorlage-Argument verwenden. Darüber hinaus zeigt Typname klarer an, dass der Name, der folgt, ein Typname ist. Der Typname wurde jedoch zu C ++ hinzugefügt, nachdem Vorlagen bereits weit verbreitet waren. Einige Programmierer verwenden weiterhin ausschließlich Klassen