O padrão “estruturas anônimas”? E, realmente, o que são eles?

O MSDN considera que as estruturas anônimas não são padrão em C ++:

Uma extensão do Microsoft C permite que você declare uma variável de estrutura dentro de outra estrutura sem lhe dar um nome. Essas estruturas aninhadas são chamadas de estruturas anônimas. C ++ não permite estruturas anônimas.

Você pode acessar os membros de uma estrutura anônima como se fossem membros da estrutura de contenção.

@ K-ballo concorda .

Disseram-me que esse recurso não é necessariamente o mesmo que apenas criar uma estrutura sem nome, mas não consigo ver uma distinção em termos de formulação padrão.

C ++ 11 diz:

[C++11: 9/1] : [..] Um especificador de class cujo header de class omite o nome de header da class define uma class sem nome.

e fornece uma construção gramatical inteira para uma definição de tipo com um nome ausente.

C ++ 03 não possui este texto explícito, mas similarmente indica que o identifier em uma definição de tipo é opcional e faz referência a “classs não nomeadas” em 9.4.2/5 e 3.5/4 .

  • Então, o MSDN está errado e essas coisas são completamente padronizadas?
  • Ou há alguma sutileza que estou perdendo entre “structs / classs sem nome” e o mesmo quando usado como membros que os impede de serem cobertos por esta funcionalidade C ++ 03 / C ++ 11?
  • Estou faltando alguma diferença fundamental entre “struct sem nome” e “struct anônimo”? Eles parecem sinônimos para mim.

Todo o texto padrão se refere à criação de uma “estrutura sem nome”:

 struct { int hi; int bye; }; 

Apenas um bom tipo amigável, sem nome acessível.

De uma maneira padrão, poderia ser instanciado como um membro assim:

 struct Foo { struct { int hi; int bye; } bar; }; int main() { Foo f; f.bar.hi = 3; } 

Mas uma “estrutura anônima” é sutilmente diferente – é a combinação de uma “estrutura sem nome” e o fato de você magicamente obter membros dela no object pai:

 struct Foo { struct { int hi; int bye; }; // <--- no member name! }; int main() { Foo f; f.hi = 3; } 

Converse com intuição , isso não cria apenas uma estrutura sem nome que é aninhada com Foo , mas também fornece automaticamente um "membro anônimo" de tipos que torna os membros acessíveis dentro do object pai.

É essa funcionalidade que não é padrão. O GCC suporta , e o mesmo acontece com o Visual C ++. Os headers da API do Windows usam esse recurso por padrão, mas você pode especificar que não deseja adicionar o #define NONAMELESSUNION antes de include os arquivos de header do Windows.

Compare com a funcionalidade padrão de "uniões anônimas" que fazem uma coisa semelhante:

 struct Foo { union { int hi; int bye; }; // <--- no member name! }; int main() { Foo f; f.hi = 3; } 

Parece que, embora o termo "sem nome" se refira ao tipo (ou seja, "a class" ou "a estrutura"), o termo "anônimo" refere-se ao próprio membro instanciado (usando um significado antigo de "struct" "está mais perto de" um object de algum tipo de struct y "). Esta foi provavelmente a raiz da sua confusão inicial.

As coisas que a Microsoft chama de estruturas anônimas não são padrão. Uma estrutura sem nome é apenas uma estrutura comum que não tem nome. Não há muito o que fazer com um, a menos que você também defina um object desse tipo:

 struct { int i; double d; } my_object; my_object.d = 2.3; 

Uniões anônimas fazem parte do padrão e têm o comportamento que você esperaria de ler a descrição da Microsoft de suas estruturas anônimas:

 union { int i; double d; }; d = 2.3; 

O padrão fala sobre uniões anônimas : [9.5] / 5

Uma união do formulário

 union { member-specification } ; 

é chamado de união anônima; define um object sem nome do tipo sem nome. A especificação de membro de uma união anônima só deve definir membros de dados não estáticos. [Nota: Tipos e funções nesteds não podem ser declarados dentro de uma união anônima. —End note] Os nomes dos membros de uma união anônima devem ser distintos dos nomes de qualquer outra entidade no escopo no qual a união anônima é declarada. Para fins de pesquisa de nomes, após a definição de sindicato anônimo, considera-se que os membros do sindicato anônimo foram definidos no escopo no qual o sindicato anônimo é declarado. [Exemplo:

 void f() { union { int a; const char* p; }; a = 1; p = "Jennifer"; } 

Aqui, a e p são usados ​​como variables ​​comuns (não-membros), mas como são membros de sindicatos, eles têm o mesmo endereço. – por exemplo

As estruturas anônimas sobre as quais a Microsoft fala são esse recurso para unions mas aplicadas a structs . Não é apenas uma definição sem nome, é importante notar que os membros da união / estrutura anônima são considerados como tendo sido definidos no escopo no qual a união / estrutura anônima é declarada.

Tanto quanto sei, não existe tal comportamento para estruturas sem nome no Padrão. Note como no exemplo citado você pode conseguir coisas que não seriam possíveis, como compartilhar armazenamento para variables ​​na pilha, enquanto estruturas anônimas não trazem nada de novo para a tabela.