Eu li isso
Promoção integral: pré-valores de tipos integrais pequenos (como char) podem ser convertidos em pré-valores de tipos integrais maiores (como int). - primeira linha
[...detalhes - não importante...]
Observe que todas as outras conversões não são promoções; por exemplo, a resolução de sobrecarga escolhe char -> int (promoção) em vez de char -> short (conversão). - linha final.
A conversão de char -> int é 'promotion' ; está claro (de um byte para 4 bytes)
A conversão de char -> short é 'não promoção'; por que?
Tenho pensado que char tem um byte e short (short int) tem dois bytes. Por que não é considerado uma promoção? Parece contradizer a primeira linha - não significa que 'converter do tipo pequeno para o tipo maior' é promoção? )
-----Editar: depois de procurar algumas respostas:
Podemos considerar "uma promoção é um caso especial de conversão"? , podemos dizer "todas as promoções são conversões, mas nem todas as conversões são promoções"?
Ou deveríamos considerá-los como dois conceitos diferentes e separados?
Motivação histórica: C
A ideia de promoções integrais remonta ao pré-padrão C. Ao fornecer argumentos para funções variadas (
...
) ou para funções sem protótipo, promoções são aplicadas. Ou seja, ligando:As promoções são basicamente uma atualização “mínima” do tipo, enquanto as conversões podem ser qualquer coisa. Você poderia até argumentar que o design é uma consequência da construção da linguagem de programação B, que nem sequer tinha vários tipos inteiros como C.
Redação relevante no padrão C++
O parágrafo relevante no C++ padrão é:
- [conv.prom] p2
A diferença entre promoções e conversões é explicada aqui:
- [conv.integral] p4
Como você pode ver, existe alguma sobreposição entre os dois conceitos, mas qualquer conversão que também seja uma promoção não é considerada uma conversão.
Impacto na resolução de sobrecarga
Como você destacou,
char -> short
é uma conversão echar -> int
uma promoção. Isto tem um impacto significativo na resolução de sobrecarga em alguns casos:Se o C++ fosse projetado do zero hoje em dia, as promoções e conversões provavelmente seriam definidas de maneira muito diferente; no entanto, o status quo é o que temos e é improvável que mude. Mudar esse comportamento e redação depois de todos esses anos é basicamente impossível devido à quantidade de código que depende disso.
Tal como acontece com tantas decisões de design em C++, a resposta é: razões históricas.
Tanto
char
paraint
quantochar
parashort
são conversões. Observe o uso de “todas as outras conversões” no texto após discutir promoções: Promoções são um tipo de conversão.Uma conversão é uma operação que recebe um valor de uma forma e produz o mesmo valor (o mais próximo possível) de outra forma:
char
valor e produzir umint
com o mesmo valor é uma conversão.int
valor e produzir uma string contendo um número decimal representando o mesmo valor é uma conversão.Em muitos lugares das expressões, o C++ converte automaticamente tipos inteiros estreitos em tipos inteiros mais amplos. Isso é feito em grande parte para fins históricos e também porque poderia ser complicado fazer aritmética puramente em tipos restritos - a
char
aritmética transbordaria muito facilmente e exigir que o programador inserisse explicitamente conversões tornaria oint
código complicado.Essas conversões especiais são chamadas de “promoções”. O significado natural da palavra em inglês, avançando para uma posição mais elevada, se ajusta a esses tipos de conversões: todas elas convertem de um tipo mais restrito para um tipo mais amplo (ou para um pelo menos tão amplo). Além disso, a palavra é adotada para designar particularmente essas conversões especiais. Uma característica importante das promoções integrais é que elas nunca alteram o valor. (Idealmente, nenhuma conversão alteraria um valor, mas isso acontece devido a restrições. Um exemplo é que a conversão de um
float
valor de 3¼ paraint
deve produzir um número inteiro, então 3 é produzido em vez de 3¼. Outro é que a conversão de umint
valor de -3 paraunsigned
força o empacotamento, de modo que um valor nominalmente muito diferente é produzido, embora tenha uma relação especial com o valor de entrada e possa ser considerado o mesmo valor no módulo aritmético.)O padrão C++ especifica um conjunto de regras para promoções integrais, e essas regras não são baseadas apenas no tamanho dos tipos. A decisão de promover a
char
para anint
em vez de ashort
é baseada no design histórico da linguagem e no desejo de comportamento consistente em diferentes plataformas.De acordo com o padrão C++, as promoções integrais são definidas para converter pequenos tipos integrais em um tipo específico definido pela implementação, que geralmente é
int
. Comoint
é escolhido como tipo de destino para promoção integral, a conversão de achar
em ashort
não se qualifica como promoção, mesmo queshort
seja maior quechar
. Em vez disso, ele se enquadra na categoria de conversões.As regras específicas podem variar entre diferentes implementações e arquiteturas, mas este é o raciocínio geral por trás do comportamento que você observou. Faz parte do design da linguagem, guiado por considerações históricas e aspectos práticos da implementação do compilador, em vez de uma progressão estritamente lógica baseada no tamanho do tipo.
A resposta curta (desculpe o trocadilho) é assim que é definido.
Claramente, passar de char (1 byte) para short (2 bytes) deve ser uma conversão "segura" (e portanto uma "promoção"?). No entanto, a seção referenciada indica especificamente quais conversões são classificadas como "promoções", e short não existe. É assim que as coisas são. Por que? Não tenho certeza - o texto diz que os operadores aritméticos não aceitam operandos menores que um int e, portanto, talvez não faça sentido "promover" para um short, quando só precisaria ser promovido para int posteriormente.