名前空間
変種
操作

通常の算術変換

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

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

目次

[編集] 定義

通常の算術変換は次のように定義されます。

[編集] ステージ1

両方のオペランドにlvalue-to-rvalue変換を適用し、結果のprvalueを元のオペランドの代わりに残りのプロセスで使用します。

[編集] ステージ2

  • いずれかのオペランドがスコープ付き列挙型である場合、変換は実行されません。もう一方のオペランドが同じ型でない場合、式は不正形式となります。
  • それ以外の場合は、次のステージに進みます。
(C++11以降)

[編集] ステージ3

  • いずれかのオペランドが列挙型であり、もう一方のオペランドが異なる列挙型または浮動小数点型である場合、式は不正形式となります。
  • それ以外の場合は、次のステージに進みます。
(C++26以降)

[編集] ステージ4

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

[編集] ステージ5

両方のオペランドは共通の型Cに変換されます。オペランドの昇格された型(整数昇格の規則による)としての型T1T2が与えられた場合、Cを決定するために次の規則が適用されます。

  • T1T2が同じ型の場合、Cはその型です。
  • それ以外の場合、T1T2が両方とも符号付き整数型であるか、または両方とも符号なし整数型である場合、C整数変換ランクが大きい方の型です。
  • それ以外の場合、T1またはT2のいずれかが符号付き整数型Sであり、もう一方が符号なし整数型Uである場合、次の規則を適用します。
  • Uの整数変換ランクがSの整数変換ランク以上の場合、CUです。
  • それ以外の場合、SUのすべての値を表すことができる場合、CSです。
  • それ以外の場合、CSに対応する符号なし整数型です。

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

(C++20以降)
(C++26まで)

[編集] 整数変換ランク

すべての整数型には、次のように定義される「整数変換ランク」があります。

  • charおよびsigned charcharが符号付きの場合)を除く、2つの符号付き整数型は、それらが同じ表現を持っていても、同じランクを持ちません。
  • 符号付き整数型のランクは、幅が小さい任意の符号付き整数型よりも大きいです。
  • 次の整数型のランクは、順に減少します。
  • long long
(C++11以降)
  • long
  • int
  • short
  • signed char
  • 任意の符号なし整数型のランクは、対応する符号付き整数型のランクと等しくなります。
  • 任意の標準整数型のランクは、同じ幅の任意の拡張整数型よりも大きいです。
(C++11以降)
  • boolのランクは、すべての標準整数型のランクよりも小さいです。
  • エンコーディング文字型(char char8_t(C++20以降)char16_tchar32_t(C++11以降)およびwchar_t)のランクは、それらの基底型のランクと等しくなります。これは次のことを意味します。
  • charのランクは、signed charおよびunsigned charのランクと等しくなります。
  • char8_tのランクは、unsigned charのランクと等しくなります。
(C++20以降)
(C++11以降)
  • wchar_tのランクは、実装定義の基底型のランクと等しくなります。
  • 同じ幅を持つ他の拡張符号付き整数型に対する、任意の拡張符号付き整数型のランクは実装定義ですが、整数変換ランクを決定するための他の規則に従います。
(C++11以降)
  • すべての整数型T1T2、およびT3について、T1T2よりもランクが高く、T2T3よりもランクが高い場合、T1T3よりもランクが高くなります。

整数変換ランクは、整数昇格の定義にも使用されます。

[編集] 浮動小数点数変換ランクとサブランク

[編集] 浮動小数点数変換ランク

すべての浮動小数点型には、次のように定義される「浮動小数点数変換ランク」があります。

  • 標準浮動小数点型のランクは、順に減少します。
    • long double
    • double
    • float
  • 浮動小数点型Tのランクは、Tの値の集合の真部分集合である値の集合を持つ任意の浮動小数点型よりも大きいです。
  • 同じ値の集合を持つ2つの拡張浮動小数点型は、等しいランクを持ちます。
  • 値の集合が、cv-非修飾標準浮動小数点型のいずれか1つと厳密に同じ値の集合を持つ拡張浮動小数点型は、その標準浮動小数点型のランクに等しいランクを持ちます。
  • 値の集合が、cv-非修飾標準浮動小数点型の2つ以上と厳密に同じ値の集合を持つ拡張浮動小数点型は、doubleのランクに等しいランクを持ちます。
(C++23から)


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

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

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

(C++23から)

[編集] 使用法

浮動小数点数変換ランクとサブランクは、次にも使用されます。

  • 異なる浮動小数点型間の変換が暗黙的に可能か、または狭窄変換であるかを判断する。
  • オーバーロード解決における変換シーケンスを区別する
(C++23から)

[編集] 不具合報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 1642 C++98 通常の算術変換はlvalueを伴う可能性がある lvalue-to-rvalue変換を最初に適用する
CWG 2528 C++20 unsigned charunsigned intの3方向比較は、
中間整数昇格のため、不正形式となる
[1]
オペランドを実際に昇格させることなく、
昇格された型に基づいて共通の型を決定する
[2]
CWG 2892 C++98 両方のオペランドが同じ
浮動小数点型である場合、「それ以上の
変換は必要ない」という意味が不明確
「それ以上の
変換は実行されない」に変更された
  1. 解決前、ステージ5の開始時にunsigned charintに昇格され、その後unsigned intに変換されます。しかし、後者の変換は狭窄であるため、3方向比較は不正形式となります。
  2. 解決後、共通の型は依然としてunsigned intです。違いは、unsigned charが中間整数昇格なしで直接unsigned intに変換されることです。この変換は狭窄ではなく、したがって3方向比較は不正形式ではありません。
English 日本語 中文(简体) 中文(繁體)