c++ - Differenza delle parole chiave "typename" e "class" nei template?


Per i modelli ho visto entrambe le dichiarazioni:

template < typename T >
template < class T >

Qual è la differenza?

E cosa significano esattamente queste parole chiave nel seguente esempio (tratto dall'articolo di Wikipedia in tedesco sui modelli)?

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


Answers


typename e class sono intercambiabili nel caso base di specificare un modello:

template<class T>
class Foo
{
};

e

template<typename T>
class Foo
{
};

sono equivalenti.

Detto questo, ci sono casi specifici in cui esiste una differenza tra typename e class .

Il primo è nel caso dei tipi dipendenti. typename è usato per dichiarare quando si fa riferimento a un tipo annidato che dipende da un altro parametro del template, come il typedef in questo esempio:

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

Il secondo che effettivamente mostri nella tua domanda, anche se potresti non rendertene conto:

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

Quando si specifica un modello di template , la parola chiave class deve essere usata come sopra - non è intercambiabile con typename in questo caso (nota: dal momento che in questo caso entrambe le parole chiave sono permesse in C ++ 17) .

Devi anche utilizzare la class quando si crea un'istanza esplicita di un modello:

template class Foo<int>;

Sono sicuro che ci sono altri casi che ho perso, ma la linea di fondo è: queste due parole chiave non sono equivalenti, e questi sono alcuni casi comuni in cui è necessario utilizzare l'uno o l'altro.




Per i parametri del modello di denominazione, typename e class sono equivalenti. §14.1.2:

Non c'è alcuna differenza semantica tra classe e nome tipografico in un parametro template.

typename tuttavia è possibile in un altro contesto quando si usano i template - per suggerire al compilatore che si sta facendo riferimento a un tipo dipendente. §14.6.2:

Si presume che un nome utilizzato in una dichiarazione o una definizione di modello e dipendente da un parametro del modello non indichi un tipo a meno che la ricerca del nome applicabile non trovi un nome di tipo o il nome sia qualificato dalla parola chiave typename.

Esempio:

typename some_template<T>::some_type

Senza typename il compilatore non può dire in generale se si riferisce a un tipo o meno.




Mentre non c'è alcuna differenza tecnica, ho visto i due usati per denotare cose leggermente diverse.

Per un modello che dovrebbe accettare qualsiasi tipo come T, inclusi i built-in (come un array)

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

Per un modello che funzionerà solo dove T è una vera classe.

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

Ma tieni presente che questa è puramente una cosa di stile che alcune persone usano. Non richiesto dallo standard o applicato dai compilatori




  1. Nessuna differenza
  2. Parametro del tipo di modello Container è esso stesso un modello con due parametri di tipo.



Questo pezzo di snippet proviene dal libro di primer c ++. Anche se sono sicuro che sia sbagliato.

Ogni parametro di tipo deve essere preceduto dalla parola chiave class o typename:

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

Queste parole chiave hanno lo stesso significato e possono essere utilizzate in modo intercambiabile all'interno di un elenco di parametri del modello. Un elenco di parametri del modello può utilizzare entrambe le parole chiave:

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

Potrebbe sembrare più intuitivo utilizzare la parola chiave typename piuttosto che la classe per designare un parametro di tipo template. Dopotutto, possiamo usare i tipi built-in (non class) come argomento di tipo template. Inoltre, typename indica chiaramente che il nome che segue è un nome di tipo. Tuttavia, typename è stato aggiunto a C ++ dopo che i template erano già in uso diffuso; alcuni programmatori continuano a utilizzare esclusivamente la classe