Namespaces
Variants

Usual arithmetic conversions

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

De nombreux opérateurs binaires qui attendent des opérandes de type arithmétique ou énumération provoquent des conversions et produisent des types de résultat de manière similaire. L'objectif est d'obtenir un type commun, qui est également le type du résultat. Ce modèle est appelé les conversions arithmétiques usuelles .

Table des matières

Définition

Les conversions arithmétiques habituelles sont définies comme suit :

Étape 1

Applique la conversion lvalue-vers-rvalue aux deux opérandes, les prvalues résultantes sont utilisées à la place des opérandes originales pour le processus restant.

Étape 2

  • Si l'un des opérandes est de type énumération scopée , aucune conversion n'est effectuée ; si l'autre opérande n'a pas le même type, l'expression est mal formée.
  • Sinon, passer à l'étape suivante.
(depuis C++11)

Étape 3

  • Si l'un des opérandes est de type énumération , et l'autre opérande est d'un type d'énumération différent ou d'un type à virgule flottante, l'expression est mal formée.
  • Sinon, passez à l'étape suivante.
(depuis C++26)

Étape 4

  • Si les deux opérandes ont le même type, aucune conversion supplémentaire n'est effectuée.
  • Sinon, si l'un des opérandes est d'un type non flottant, cet opérande est converti vers le type de l'autre opérande.
  • Sinon, si les rangs de conversion en virgule flottante des types des opérandes sont ordonnés mais (depuis C++23) non égaux, alors l'opérande du type avec le rang de conversion en virgule flottante inférieur est converti vers le type de l'autre opérande.
  • Sinon, si les rangs de conversion en virgule flottante des types des opérandes sont égaux, alors l'opérande ayant le sous-rang de conversion en virgule flottante inférieur est converti vers le type de l'autre opérande.
  • Sinon, l'expression est mal formée.
(depuis C++23)
  • Sinon, les deux opérandes sont de types entiers, passez à l'étape suivante.

Étape 5

Les deux opérandes sont convertis en un type commun C . Étant donné les types T1 et T2 comme type promu ( selon les règles de promotion intégrale ) des opérandes, les règles suivantes sont appliquées pour déterminer C :

  • Si T1 et T2 sont du même type, C est ce type.
  • Sinon, si T1 et T2 sont tous deux des types entiers signés ou tous deux des types entiers non signés, C est le type ayant le plus grand rang de conversion entière .
  • Sinon, un type entre T1 et T2 est un type entier signé S , l'autre type est un type entier non signé U . Appliquer les règles suivantes :
  • Si le rang de conversion entier de U est supérieur ou égal au rang de conversion entier de S , C est U .
  • Sinon, si S peut représenter toutes les valeurs de U , C est S .
  • Sinon, C est le type entier non signé correspondant à S .

Si un opérande est de type énumération et l'autre opérande est d'un type d'énumération différent ou d'un type à virgule flottante, ce comportement est déprécié.

(depuis C++20)
(jusqu'à C++26)

Rang de conversion des entiers

Chaque type entier possède un rang de conversion entier défini comme suit :

  • Aucun deux types entiers signés autres que char et signed char (si char est signé) n'ont le même rang, même s'ils ont la même représentation.
  • Le rang d'un type entier signé est supérieur au rang de tout type entier signé ayant une largeur inférieure.
  • Les rangs des types entiers suivants diminuent dans l'ordre :
  • long long
(depuis C++11)
  • long
  • int
  • short
  • signed char
**Note:** Le texte à traduire dans ce fragment HTML se compose uniquement de termes spécifiques au C++ (`long`, `int`, `short`, `signed char`), qui ne doivent pas être traduits selon vos instructions. Par conséquent, le contenu reste identique.
  • Le rang de tout type entier non signé est égal au rang du type entier signé correspondant.
  • Le rang de tout type entier standard est supérieur au rang de tout type entier étendu de même largeur.
(depuis C++11)
  • Le rang de bool est inférieur au rang de tous les types entiers standards.
  • Les rangs des types de caractères d'encodage ( char , char8_t (depuis C++20) , char16_t , char32_t , (depuis C++11) et wchar_t ) sont égaux aux rangs de leurs types sous-jacents , ce qui signifie :
  • Le rang de char est égal au rang de signed char et unsigned char .
  • Le rang de char8_t est égal au rang de unsigned char .
(depuis C++20)
(depuis C++11)
  • Le rang de wchar_t est égal au rang de son type sous-jacent défini par l'implémentation.
  • Le rang de tout type entier signé étendu par rapport à un autre type entier signé étendu de même largeur est défini par l'implémentation, mais reste soumis aux autres règles de détermination du rang de conversion entier.
(depuis C++11)
  • Pour tous les types entiers T1 , T2 , et T3 , si T1 a un rang supérieur à T2 et T2 a un rang supérieur à T3 , alors T1 a un rang supérieur à T3 .

Le rang de conversion entier est également utilisé dans la définition de la promotion intégrale .

Rang et sous-rang de conversion en virgule flottante

Rang de conversion en virgule flottante

Chaque type à virgule flottante possède un rang de conversion à virgule flottante défini comme suit :

  • Les rangs des types à virgule flottante standard diminuent dans l'ordre :
    • long double
    • double
    • float
  • Le rang d'un type à virgule flottante T est supérieur au rang de tout type à virgule flottante dont l'ensemble des valeurs est un sous-ensemble propre de l'ensemble des valeurs de T .
  • Deux types à virgule flottante étendus avec le même ensemble de valeurs ont des rangs égaux.
  • Un type à virgule flottante étendu avec le même ensemble de valeurs qu'exactement un type à virgule flottante standard non qualifié cv a un rang égal au rang de ce type à virgule flottante standard.
  • Un type à virgule flottante étendu avec le même ensemble de valeurs que plus d'un type à virgule flottante standard non qualifié cv a un rang égal au rang de double .
(depuis C++23)


Sous-rang de conversion en virgule flottante

Les types en virgule flottante ayant un rang de conversion égal sont ordonnés par le sous-rang de conversion en virgule flottante . Le sous-rang forme un ordre total parmi les types ayant des rangs égaux.

Les types std::float16_t , std::float32_t , std::float64_t , et std::float128_t ( types en virgule flottante à largeur fixe ) ont un sous-rang de conversion supérieur à tout type en virgule flottante standard ayant un rang de conversion égal. Sinon, l'ordre du sous-rang de conversion est défini par l'implémentation.

(depuis C++23)

Utilisation

Le rang de conversion en virgule flottante et le sous-rang sont également utilisés pour

(depuis C++23)

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement tel que publié Comportement correct
CWG 1642 C++98 les conversions arithmétiques habituelles pouvaient impliquer des lvalues applique d'abord les conversions lvalue-vers-rvalue
CWG 2528 C++20 la comparaison à trois voies entre unsigned char
et unsigned int est mal formée en raison
de la promotion intégrale intermédiaire [1]
détermine le type commun basé
sur les types promus, sans
promouvoir réellement les opérandes [2]
CWG 2892 C++98 lorsque les deux opérandes sont du même
type à virgule flottante, la signification de « aucune
conversion supplémentaire n'est nécessaire » n'était pas claire
modifié en « aucune conversion
supplémentaire ne sera effectuée »
  1. Avant la résolution, unsigned char est promu en int au début de l'étape 5, puis il est converti en unsigned int . Cependant, cette dernière conversion est rétrécissante, ce qui rend la comparaison à trois voies mal formée.
  2. Après la résolution, le type commun reste unsigned int . La différence est que unsigned char est directement converti en unsigned int sans la promotion intégrale intermédiaire. La conversion n'est pas rétrécissante et donc la comparaison à trois voies est bien formée.