estruturas de punição de união com “sequência inicial comum”: Por que C (99+), mas não C ++, estipula uma 'declaração visível do tipo de união'?

fundo

Discussões sobre a natureza da punição de tipo definida pela não-ou-implementação por meio de umunion normalmente cite os seguintes bits, aqui via @ecatmur (https://stackoverflow.com/a/31557852/2757035 ), com uma isenção para layout padrãostructs com uma "sequência inicial comum" dos tipos de membros:

C11 (6.5.2.3 Estrutura e membros do sindicato; Semântica):

[...] se uma união contiver várias estruturas que compartilham uma sequência inicial comum (veja abaixo), e se o objeto da união contiver atualmente uma dessas estruturas, é permitido inspecionar a parte inicial comum de qualquer uma delasem qualquer lugar em que uma declaração do tipo completo de união seja visível. Duas estruturas compartilham umsequência inicial comum se os membros correspondentes tiverem tipos compatíveis (e, para campos de bits, as mesmas larguras) para uma sequência de um ou mais membros iniciais.

C ++ 03 ([class.mem] / 16):

Se uma união POD contiver duas ou mais estruturas POD que compartilham uma sequência inicial comum, e se o objeto de união POD contiver atualmente uma dessas estruturas POD, é permitido inspecionar a parte inicial comum de qualquer uma delas. Duas estruturas POD compartilham uma sequência inicial comum se os membros correspondentes tiverem tipos compatíveis com layout (e, para campos de bits, as mesmas larguras) para uma sequência de um ou mais membros iniciais.

Outras versões dos dois padrões têm linguagem semelhante; desde C ++ 11, a terminologia usada élayout padrão ao invés dePOD.

Como nenhuma reinterpretação é necessária, isso não é realmente punição de tipo, apenas substituição de nome aplicada aunion acessos de membros. Uma proposta para C ++ 17 (o infame P0137R1) torna isso explícito usando uma linguagem como 'o acesso é como se o outro membro da estrutura fosse nomeado'.

Mas observe o negrito - "em qualquer lugar em que uma declaração do tipo completo de união seja visível"- uma cláusula que existe no C11, mas que não existe nos rascunhos do C ++ para 2003, 2011 ou 2014 (todas quase idênticas, mas versões posteriores substituem" POD "pelo novo termolayout padrão) De qualquer forma, a 'declaração visível deunion O tipo bit está totalmente ausente na seção correspondente de qualquer padrão C ++.

@loop e @ Mints97, aqui -https://stackoverflow.com/a/28528989/2757035 - mostre que essa linha também foiausente em C89, aparecendo pela primeira vez em C99 e permanecendo em C desde então (embora, novamente, nunca seja filtrado para C ++).

Discussões sobre padrões em torno deste

[cortou - veja minha resposta]

Questões

A partir disso, minhas perguntas foram:

O que isto significa? O que é classificado como uma 'declaração visível'? Esta cláusula pretendia restringir - ou expandir - a gama de contextos em que essa 'punição' definiu um comportamento?

Devemos assumir que essa omissão no C ++ é muito deliberada?

Qual é a razão para C ++ diferir de C? O C ++ acabou de 'herdar' isso do C89 e então decidiu - ou pior,esqueço - atualizar ao lado do C99?

Se a diferença for intencional, entãoQue benefícios ou desvantagens existem para os 2 tratamentos diferentes em C vs C ++?

Que ramificações interessantes, se houver alguma, possuem em tempo de compilação ou tempo de execução? Por exemplo, @ecatmur, em um comentário respondendo ao apontar isso em sua resposta original (link acima), especulou da seguinte maneira.

Eu imagino que permite uma otimização mais agressiva; C pode assumir que argumentos de funçãoS* s eT* t não alias, mesmo que compartilhem uma sequência inicial comum, desde que nãounion { S; T; } está em exibição, enquanto o C ++ pode fazer essa suposição apenas no tempo do link. Pode valer a pena fazer uma pergunta separada sobre essa diferença.

Bem, aqui estou eu perguntando! Estou muito interessado em alguma opinião sobre isso, especialmente: outras partes relevantes do Padrão, citações de membros do comitê ou outros comentadores estimados, insights de desenvolvedores que podem ter notado uma diferença prática devido a isso - assumindo qualquer compiladorincomoda para impor a cláusula adicionada de C - e etc. O objetivo é gerar um catálogo útil de fatos relevantes sobre essa cláusula C e sua omissão (intencional ou não) de C ++. Então vamos!