À l'occasion, j'ai vu des messages d'erreur vraiment indéchiffrables crachés gcc
lors de l'utilisation de modèles ... Plus précisément, j'ai eu des problèmes où des déclarations apparemment correctes provoquaient des erreurs de compilation très étranges qui disparaissaient comme par magie en préfixant le typename
mot - clé au début du déclaration ... (Par exemple, la semaine dernière, je déclarais deux itérateurs comme membres d'une autre classe basée sur un modèle et je devais le faire) ...
Quelle est l'histoire typename
?
Réponses:
Voici la citation du livre de Josuttis:
la source
typename
(mais pas tous!).Le post BLog de Stan Lippman suggère: -
Donc, fondamentalement, Stroustrup a réutilisé le mot-clé de classe sans introduire un nouveau mot-clé qui est modifié par la suite dans la norme pour les raisons suivantes
Comme l'exemple donné
la grammaire du langage est mal interprétée
T::A *aObj;
comme une expression arithmétique, donc un nouveau mot-clé est introduit appelétypename
il demande au compilateur de traiter l'instruction suivante comme une déclaration.
C'est pourquoi nous avons les deux
Vous pouvez jeter un œil à ce post , il vous aidera certainement, j'en ai juste extrait autant que je pourrais
la source
typename
nécessaire, si vous pouviez utiliser le mot-clé existantclass
dans le même but?typename
est devenu nécessaire pour résoudre le problème d'analyse tel que décrit dans la réponse de Naveen en citant Josuttis. (Je ne pense pas que l'insertion d'unclass
à cet endroit aurait fonctionné.) Ce n'est qu'après que le nouveau mot-clé a été accepté pour ce cas, il a également été autorisé dans les déclarations d'argument de modèle ( ou est-ce que c'est des définitions? ), Carclass
il y a toujours eu un peu trompeur.Considérez le code
Malheureusement, le compilateur n'est pas obligé d'être psychique, et ne sait pas si T :: Sometype finira par faire référence à un nom de type ou à un membre statique de T. Donc, on utilise
typename
pour le dire:la source
Dans certaines situations où vous faites référence à un membre de soi-disant dépendant type (signifiant "dépendant du paramètre du modèle"), le compilateur ne peut pas toujours déduire sans ambiguïté la signification sémantique de la construction résultante, car il ne sait pas quel type de nom c'est (c'est-à-dire s'il s'agit d'un nom d'un type, d'un nom d'un membre de données ou d'un nom d'autre chose). Dans de tels cas, vous devez lever l'ambiguïté de la situation en indiquant explicitement au compilateur que le nom appartient à un nom de type défini comme membre de ce type dépendant.
Par exemple
Dans cet exemple, le mot-clé est
typename
nécessaire à la compilation du code.La même chose se produit lorsque vous souhaitez faire référence à un membre de modèle de type dépendant, c'est-à-dire à un nom qui désigne un modèle. Vous devez également aider le compilateur en utilisant le mot-clé
template
, bien qu'il soit placé différemmentDans certains cas, il peut être nécessaire d'utiliser les deux
(si j'ai la syntaxe correctement).
Bien sûr, un autre rôle du mot
typename
- clé est d'être utilisé dans les déclarations de paramètres de modèle.la source
Le secret réside dans le fait qu'un modèle peut être spécialisé pour certains types. Cela signifie qu'il peut également définir l'interface complètement différente pour plusieurs types. Par exemple, vous pouvez écrire:
On pourrait se demander pourquoi est-ce utile et en effet: cela semble vraiment inutile. Mais gardez à l'esprit que, par exemple,
std::vector<bool>
lereference
type est complètement différent de celui des autresT
s. Certes, cela ne change pas le genre dereference
type à quelque chose de différent, mais cela peut néanmoins arriver.Maintenant, que se passe-t-il si vous écrivez vos propres modèles en utilisant ce
test
modèle. Quelque chose comme çacela semble vous convenir car vous vous attendez à ce que ce
test<T>::ptr
soit un type. Mais le compilateur ne sait pas et en fait il est même conseillé par la norme d'attendre le contraire, cetest<T>::ptr
n'est pas un type. Pour dire au compilateur ce que vous attendez, vous devez ajouter untypename
avant. Le modèle correct ressemble à ceciBottom line: Vous devez ajouter
typename
avant chaque fois que vous utilisez un type imbriqué de modèle dans vos modèles. (Bien sûr, uniquement si un paramètre de modèle de votre modèle est utilisé pour ce modèle interne.)la source
Deux utilisations:
template
mot clé d'argument (au lieu declass
)typename
mot clé indique au compilateur qu'un identificateur est un type (plutôt qu'une variable membre statique)la source
Je pense que toutes les réponses ont mentionné que le
typename
mot - clé est utilisé dans deux cas différents:a) Lors de la déclaration d'un paramètre de type de modèle. par exemple
Qui il n'y a aucune différence entre eux et ils sont exactement les mêmes.
b) Avant d'utiliser un nom de type dépendant imbriqué pour un modèle.
Le fait de ne pas utiliser
typename
entraîne des erreurs d'analyse / compilation.Ce que je veux ajouter au deuxième cas, comme mentionné dans le livre de Scot Meyers Effective C ++ , c'est qu'il existe une exception à l'utilisation
typename
avant un nom de type dépendant imbriqué . L'exception est que si vous utilisez le nom de type dépendant imbriqué comme classe de base ou dans une liste d'initialisation de membre , vous ne devez pas l'utilisertypename
:Remarque: l' utilisation
typename
pour le deuxième cas (c'est-à-dire avant le nom de type dépendant imbriqué) n'est pas nécessaire depuis C ++ 20.la source
la source