Perché c'è un nome di classe iniettato?


147

Di recente, ho visto una strana caratteristica C ++: il nome della classe 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 funzionalità non esisteva nel vecchio C ++. Quindi, quando è stato introdotto? C ++ 03? C ++ 11?


Amico, puoi guardare su Skype? Non posso raggiungerti
Irinel Iovan il

Risposte:


162

Il nome della classe iniettata significa che Xè dichiarato come membro di X, quindi la ricerca del nome all'interno Xtrova sempre la classe corrente, non un'altra Xche potrebbe essere dichiarata nello stesso ambito racchiuso, ad es.

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

La create()funzione crea un Xoggetto temporaneo o chiama la funzione X? Nell'ambito dello spazio dei nomi, chiamerebbe la funzione, quindi lo scopo del nome della classe iniettato è quello di assicurarsi che all'interno del corpo del Xnome trovi sempre la classe stessa (perché la ricerca del nome inizia nel proprio ambito della classe prima di guardare tra scopo).

È anche utile all'interno dei modelli di classe, in cui il nome della classe iniettato può essere utilizzato senza un elenco di argomenti del modello, ad esempio utilizzando semplicemente al Fooposto dell'ID modello completo Foo<blah, blah, blah>, quindi è facile fare riferimento all'istanza corrente. Vedere DR 176 per una modifica tra C ++ 98 e C ++ 03 che lo chiarisca.

L'idea del nome della classe iniettata era presente in C ++ 98, ma la terminologia era nuova per C ++ 03.

C ++ 98 dice:

Un nome di classe viene inserito nell'ambito in cui viene dichiarato immediatamente dopo la visualizzazione del nome di classe . Il nome della classe viene inoltre inserito nell'ambito della classe stessa.

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

Un nome di classe viene inserito nell'ambito in cui viene dichiarato immediatamente dopo la visualizzazione del nome di classe . Il nome della classe viene anche inserito nell'ambito della classe stessa; questo è noto come il nome della classe iniettata .

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

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

  • Per esempio,

    class link { link* next; };


2
Mi è stato chiesto abbastanza spesso, ma non ho mai potuto creare un semplice esempio indicando il problema. Quindi +1 Per l'esempio.
Dhein,

1
Questo può essere visto chiaramente se esegui clang ++ your_program.cpp -Xclang -ast-dump e vedi la tua classe e quindi un nodo figlio di classe iniettato.
xaxxon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.