web-dev-qa-db-fra.com

Pourquoi le nom de type n'est-il pas requis pour une classe de base qui est un type imbriqué?

J'ai été très surpris de voir qu'il n'est pas nécessaire d'ajouter typename lorsqu'un type dépendant apparaît comme classe de base:

struct B {};

struct wr
{ typedef B type; };

template<class T>
struct A : T::type
{};

int main()
{
    A<wr> a;
    (void)a;
}

Pourquoi typename n'est-il pas requis devant T::type?

25
Peregring-lk

C'est un cas spécial, comme d'autres l'ont noté. Pour citer la norme à ce sujet:

[temp.res]

5 Un nom qualifié utilisé comme nom dans un class-or-decltype ou un spécificateur de type élaboré est implicitement supposé nommer un type, sans utiliser le mot-clé typename. Dans un spécificateur de nom imbriqué qui contient immédiatement un spécificateur de nom imbriqué qui dépend d'un paramètre de modèle, l'identificateur ou l'ID de modèle simple est implicitement supposé nommer un type, sans utiliser le mot clé typename. [Remarque: Le mot clé typename n'est pas autorisé par la syntaxe de ces constructions. - note de fin]

Et en C++ 20, il y aura encore plus d'exceptions à la nécessité de typename.

Pourquoi typename n'est-il pas requis devant T::type?

Parce que vous ne pouvez pas hériter d'une valeur. Vous utilisez typename pour dire au compilateur qu'un identifiant imbriqué donné est un type, mais pour l'héritage, cela doit être le cas de toute façon afin que vous puissiez l'omettre - c'est pourquoi le langage fournit une exception à typename- règle pour les spécificateurs de base. De cppreference (accent sur le mien):

L'ambiguïté typename pour les noms dépendants

Dans une déclaration ou une définition d'un modèle, y compris un modèle d'alias, un nom qui n'est pas membre de l'instanciation actuelle et qui dépend d'un paramètre de modèle n'est pas considéré comme un type sauf si le mot-clé nom_type est utilisé ou sauf s'il a déjà été établi comme nom de type , par exemple avec une déclaration typedef ou en étant utilisé pour nommer une classe de base .

Notez que nous aurons plus d'endroits où typename peut être omis, voir P0634 .

19
lubgr

Vous n'avez besoin d'utiliser typename que si vous devez dire au compilateur de s'attendre à un type plutôt qu'à autre chose.

Comme seul un type peut être hérité, il n'y a pas d'ambiguïté, donc typename est superflu.

5
Bathsheba