Sizeof (enum) pode diferir de sizeof (std :: subjac_type <Enum> :: type)?

16

Recentemente, surgiu uma revisão de código que, no exemplo a seguir:

enum class A : uint8_t
{
    VAL1, VAL2 
};

...
std::vector<A> vOfA; // Assume this is sized and full of some stuff.
std::memcpy(wire_buffer, vOfA.data(), vOfA.size() * sizeof(A));

Deveríamos estar usando em sizeof(std::underlying_type<A>::type)vez de sizeof(A). É possível que estes possam diferir? Alguém tem uma cotação de padrões que garanta isso?

Fantastic Mr Fox
fonte
Vinculando qual é o tamanho de um tipo de dados enum em C ++? (que também deve ser feito para cobrir os escopos :-).
Acorn
3
Mesmo que sejam do mesmo tamanho (o que é mais do que provável), qual é o argumento contra o uso sizeof(A)? Além disso: se eles tiverem um tamanho diferente (improvável), o uso sizeof(std::underlying_type<A>)seria completamente errado.
Sander De Dycker 03/12/19
11
sizeof(std::underlying_type<A>)é provavelmente 1. Você quis dizer ::type?
LF
11
@SanderDeDycker Sim, quando se lida com As, definitivamente se deseja usar sizeof(A)e o código não deve se importar com o tipo de tipo A.
Acorn
@ LF Sim, erro de digitação. O título estava correto.
Fantastic Mr Fox

Respostas:

12

No C ++ 03, era garantido (bem, para enumerações sem escopo, de qualquer maneira).

[dcl.enum] Declarações de enumeração (ênfase minha)

6 O tipo subjacente de uma enumeração é um tipo integral que pode representar todos os valores do enumerador definidos na enumeração. Se nenhum tipo integral puder representar todos os valores do enumerador, a enumeração está incorreta. É definido pela implementação qual tipo integral é usado como o tipo subjacente para uma enumeração, exceto que o tipo subjacente não deve ser maior que int, a menos que o valor de um enumerador não possa caber em um int ou não assinado. Se a lista de enumeradores estiver vazia, o tipo subjacente é como se a enumeração tivesse um único enumerador com o valor 0. O valor de sizeof()aplicado a um tipo de enumeração, um objeto de tipo de enumeração ou um enumerador, é o valor sizeof()aplicado a tipo subjacente .

Depois veio o n2347 , o artigo que foi adotado para enumerações fortemente tipadas ( enum class) e outros aprimoramentos para enumerações sem escopo, e teve a sentença em negrito removida. Curiosamente, uma versão anterior da proposta, n2213 , substituiu a sentença removida. Mas não entrou na versão adotada.

Portanto, no C ++ moderno, não há obrigação de os tamanhos serem os mesmos. Embora do ponto de vista prático, é improvável que as implementações tenham alterado o comportamento prescrito pelo C ++ 03 para tamanhos de enumeração.

Pode-se considerar um defeito no padrão.

Contador de Histórias - Monica Sem Calúnia
fonte
2
Como algo pode ter sido garantido no C ++ 03 para um recurso que não existia na linguagem? oO
Corridas de leveza em órbita
4
@LightnessRaceswithMonica - A noção de um tipo subjacente não é nova. Só que o C ++ 11 permitiu que você o especificasse.
StoryTeller - Unslander Monica
Eu sei disso. A noção de um enum com escopo ( enum class) é nova.
Lightness Races in Orbit
@LightnessRaceswithMonica - Eu acho que potencialmente podemos culpar a proposta aqui. Ele fez duas coisas, introduziu enumerações de escopo e permitiu que todas as enumerações (não apenas as de escopo) tivessem seu tipo subjacente definido. Daí o "garantido" em C ++ 03.
StoryTeller - Unslander Monica
11
@ StoryTeller-UnslanderMonica Sim, a pergunta é a mesma que eu acho, com escopo ou sem escopo.
Fantastic Mr Fox