Perché c’è un nome di class inserito?

Recentemente, ho visto una strana caratteristica del C ++: nome class iniettato .

class X { }; X x1; class X::X x2; // class X::X is equal to X class X::X::X x3; // ...and so on... 

Ma non riesco a capire perché questa funzione sia necessaria. C’è qualche pratica che richiede questa funzione?

E ho sentito che questa funzione non esisteva nel vecchio C ++. Quindi, quando è stato introdotto? C ++ 03? C ++ 11?

Il nome della class iniettata significa che X è dichiarato come membro di X , quindi la ricerca del nome all’interno di X trova sempre la class corrente, non un’altra X che potrebbe essere dichiarata nello stesso ambito di chiusura, ad esempio

 void X() { } class X { public: static X create() { return X(); } }; 

La funzione create() crea un object X temporaneo o chiama la funzione X ? Nell’ambito dello spazio dei nomi chiamerebbe la funzione, quindi lo scopo del nome della class immessa è quello di garantire che all’interno del corpo di X il nome trovi sempre la class stessa (poiché la ricerca del nome inizia nel campo di visibilità della class prima di cercare nel ambito di applicazione).

È anche utile all’interno dei modelli di class, dove il nome della class iniettata può essere usato senza un elenco di argomenti del template, ad esempio usando semplicemente Foo invece del modello completo Foo , quindi è facile fare riferimento all’istanza corrente . Vedi DR 176 per una modifica tra C ++ 98 e C ++ 03 che lo ha chiarito.

L’idea del nome di class iniettato era presente in C ++ 98, ma la terminologia era nuova per C ++ 03.

C ++ 98 dice:

Un nome di class viene inserito nello scope in cui viene dichiarato immediatamente dopo la visualizzazione del nome della class . Il nome della class viene anche inserito nell’ambito della class stessa.

La seconda frase è stata modificata da DR 147, quindi C ++ 03 dice in [class] / 2:

Un nome di class viene inserito nello scope in cui viene dichiarato immediatamente dopo la visualizzazione del nome della class . Il nome della class viene anche inserito nell’ambito della class stessa; questo è noto come nome della class iniettata .

Anche prima del C ++ 98, l’ARM ha una formulazione approssimativamente equivalente che significa che il nome della class ‘può sempre essere usato nel corpo della class per fare riferimento alla class stessa:

Il nome di una class può essere usato come nome di class anche all’interno dell’elenco dei membri dello stesso identificatore di class.

  • Per esempio,

    class link { link* next; };