Por que existe um nome de classe injetado?

147

Recentemente, vi um recurso estranho do C ++: nome da classe injetada .

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

Mas não consigo descobrir por que esse recurso é necessário. Existe alguma prática que requer esse recurso?

E ouvi dizer que esse recurso não existia no C ++ antigo. Então, quando foi introduzido? C ++ 03? C ++ 11?

ikh
fonte
Amigo, você pode procurar no Skype? Não consigo
entrar em

Respostas:

162

O nome da classe injetada significa que Xé declarado como membro de X, para que a pesquisa de nome Xsempre encontre a classe atual, e não outra Xque possa ser declarada no mesmo escopo, por exemplo

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

A create()função está criando um Xobjeto temporário ou chamando a função X? No escopo do espaço para nome, ele chamaria a função; portanto, o objetivo do nome da classe injetado é garantir que, dentro do corpo do Xnome, sempre encontre a própria classe (porque a pesquisa de nome começa no próprio escopo da classe antes de procurar no anexo) escopo).

Também é útil dentro de modelos de classe, onde o nome da classe injetada pode ser usado sem uma lista de argumentos de modelo, por exemplo, usando simplesmente em Foovez do ID completo do modelo Foo<blah, blah, blah>, para facilitar a consulta à instanciação atual. Veja DR 176 para uma alteração entre C ++ 98 e C ++ 03 que esclareceu isso.

A idéia do nome da classe injetada estava presente no C ++ 98, mas a terminologia era nova no C ++ 03.

O C ++ 98 diz:

Um nome de classe é inserido no escopo em que é declarado imediatamente após a visualização do nome da classe . O nome da classe também é inserido no escopo da própria classe.

A segunda sentença foi alterada pelo DR 147, então o C ++ 03 diz em [class] / 2:

Um nome de classe é inserido no escopo em que é declarado imediatamente após a visualização do nome da classe . O nome da classe também é inserido no escopo da própria classe; isso é conhecido como nome da classe injetado .

Mesmo antes do C ++ 98, o ARM possui uma expressão aproximadamente equivalente, o que significa que o nome da classe sempre pode ser usado no corpo da classe para se referir à própria classe:

O nome de uma classe pode ser usado como um nome de classe, mesmo dentro da lista de membros do próprio especificador de classe.

  • Por exemplo,

    class link { link* next; };

Jonathan Wakely
fonte
2
Muitas vezes me perguntam isso, mas nunca consegui criar um exemplo simples apontando o problema. Então +1 Para o exemplo.
Dhein
1
Isso pode ser visto claramente se você executar clang ++ your_program.cpp -Xclang -ast-dump e vir sua classe e, em seguida, um nó filho da classe injetado.
Xxxxon