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

多くの二項演算子は、 算術型 または 列挙型 のオペランドを期待し、同様の方法で変換を引き起こし、結果型を生成します。その目的は、結果の型でもある共通の型を生成することです。このパターンは 通常の算術変換 と呼ばれます。

目次

定義

通常の算術変換は以下のように定義されます:

ステージ1

両方のオペランドに lvalue-to-rvalue conversion を適用し、結果のprvalueを残りの処理において元のオペランドの代わりに使用します。

ステージ2

  • どちらかのオペランドが scoped enumeration type の場合、変換は行われない。もう一方のオペランドが同じ型を持たない場合、式は不適格となる。
  • それ以外の場合、次の段階に進む。
(C++11以降)

ステージ3

  • どちらかのオペランドが 列挙型 であり、もう一方のオペランドが異なる列挙型または浮動小数点型の場合、その式は不適格となる。
  • それ以外の場合、次の段階に進む。
(C++26以降)

ステージ4

  • いずれかのオペランドが 浮動小数点型 の場合、以下の規則が適用されます:
  • 両方のオペランドが同じ型を持つ場合、それ以上の変換は行われません。
  • そうでなく、一方のオペランドが非浮動小数点型の場合、そのオペランドはもう一方のオペランドの型に変換されます。
  • そうでなく、オペランドの型の 浮動小数点変換ランク 順序付けられており (C++23以降) 等しくない場合、浮動小数点変換ランクが小さい方の型のオペランドはもう一方のオペランドの型に変換されます。
  • それ以外の場合、オペランドの型の浮動小数点変換ランクが等しい場合、より小さい 浮動小数点変換サブランク を持つオペランドがもう一方のオペランドの型に変換される。
  • それ以外の場合、式は不適格となる。
(C++23以降)
  • それ以外の場合、両方のオペランドは整数型であり、次の段階に進みます。

ステージ5

両方のオペランドは共通の型 C に変換されます。 T1 T2 をオペランドの昇格型( 整数昇格の規則 に基づく)として、以下の規則が C を決定するために適用されます:

  • T1 T2 が同じ型の場合、 C はその型となる。
  • それ以外の場合、 T1 T2 が両方とも符号付き整数型または両方とも符号なし整数型の場合、 C はより大きい 整数変換ランク を持つ型となる。
  • それ以外の場合、 T1 T2 の一方が符号付き整数型 S で、もう一方が符号なし整数型 U となる。以下の規則を適用する:
  • U の整数変換順位が S の整数変換順位以上の場合、 C U となる。
  • それ以外の場合、 S U の全ての値を表現できるならば、 C S となる。
  • それ以外の場合、 C S に対応する符号なし整数型となる。

一方のオペランドが列挙型で、もう一方のオペランドが異なる列挙型または浮動小数点型である場合、この動作は非推奨です。

(since C++20)
(until C++26)

整数変換ランク

すべての 整数型 には、以下のように定義される 整数変換ランク があります:

  • char および signed char char が符号付きの場合)を除き、同じ表現を持つ場合でも、2つの符号付き整数型が同じランクを持つことはない。
  • 符号付き整数型のランクは、より小さい幅を持つ符号付き整数型のランクよりも大きい。
  • 以下の整数型のランクは、順に減少する:
  • long long
(C++11以降)
  • long
  • int
  • short
  • signed char
  • 符号なし整数型のランクは、対応する符号付き整数型のランクと等しい。
  • 同じ幅を持つ拡張整数型の順位よりも、任意の標準整数型の順位の方が大きい。
(C++11以降)
  • bool の順位は、すべての標準整数型の順位より低い。
  • 符号化文字型( char char8_t (C++20以降) char16_t char32_t (C++11以降) および wchar_t )の順位は、それらの 基盤となる型 の順位と等しい。すなわち:
  • char のランクは、 signed char および unsigned char のランクと等しい。
  • char8_t の順位は unsigned char の順位と等しい。
(C++20以降)
(C++11以降)
  • wchar_t のランクは、実装定義の基盤となる型のランクと等しい。
  • 同じ幅を持つ他の拡張符号付き整数型に対する任意の拡張符号付き整数型の順位は実装定義であるが、整数変換順位を決定するための他の規則には従う。
(C++11以降)
  • すべての整数型 T1 T2 T3 について、 T1 のランクが T2 より高く、かつ T2 のランクが T3 より高い場合、 T1 のランクは T3 より高くなる。

整数変換順位はまた、 整数プロモーション の定義にも使用されます。

浮動小数点変換ランクとサブランク

浮動小数点変換ランク

すべての 浮動小数点型 は、以下のように定義される 浮動小数点変換ランク を持ちます:

  • 標準浮動小数点型のランクは以下の順序で減少します:
    • long double
    • double
    • float
  • 浮動小数点型 T のランクは、 T の値の集合が真部分集合である浮動小数点型のランクよりも大きい。
  • 同じ値の集合を持つ2つの拡張浮動小数点型は、同じランクを持つ。
  • 厳密に1つのcv修飾なし標準浮動小数点型と同じ値の集合を持つ拡張浮動小数点型は、その標準浮動小数点型と同じランクを持つ。
  • 複数のcv修飾なし標準浮動小数点型と同じ値の集合を持つ拡張浮動小数点型は、 double と同じランクを持つ。
(C++23以降)


浮動小数点変換サブランク

同じ浮動小数点変換ランクを持つ浮動小数点型は、 浮動小数点変換サブランク によって順序付けられます。サブランクは同じランクを持つ型間の全順序を形成します。

std::float16_t std::float32_t std::float64_t 、および std::float128_t 固定幅浮動小数点型 )は、同じ変換ランクを持つ標準浮動小数点型よりも大きな変換サブランクを持ちます。それ以外の場合、変換サブランクの順序は実装定義です。

(C++23以降)

使用方法

浮動小数点変換ランクとサブランクもまた、以下の目的で使用されます。

  • std::num_get::get() による拡張浮動小数点型の抽出において、実際に抽出される型を決定する、
  • std::num_put::put() による拡張浮動小数点型の挿入において、実際に挿入される型を決定する、
(C++23以降)

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
CWG 1642 C++98 通常の算術変換が左辺値を含む可能性があった 左辺値から右辺値への変換を先に適用
CWG 2528 C++20 unsigned char unsigned int の三方比較が
中間的な整数昇格により不適格となっていた [1]
オペランドを実際に昇格させずに、
昇格後の型に基づいて共通の型を決定 [2]
CWG 2892 C++98 両オペランドが同じ浮動小数点型の場合、
「これ以上の変換は不要」の意味が不明確だった
「これ以上の変換は実行されない」
に変更
  1. この解決策の前は、 unsigned char はステージ5の開始時に int に昇格され、その後 unsigned int に変換されます。しかし、後者の変換は縮小変換であるため、三方比較が不適格となります。
  2. この解決策の後も、共通の型は依然として unsigned int です。違いは、 unsigned char が中間の整数昇格なしに直接 unsigned int に変換されることです。この変換は縮小変換ではないため、三方比較は適格となります。