const_cast の仕様

まあ調べたかったのは、const_cast して未定義動作になるのはどんな場合かってだけなんだけど、ある程度翻訳したので一応載せてみる。

式 const_cast(v) の結果は T である。もし T が lvalue reference 型か function 型への rvalue reference 型である場合、結果は lvalue だ。もし T が object 型への rvalue reference 型である場合、結果は xvalue だ。それ以外の場合、結果は prvalue で、lvalue-to-rvalue, array-to-pointer, function-to-pointer 標準変換が、式 v に適用される。const_cast を使って明示的に適用することができる変換は以下のリストの通りだ。それ以外の変換は const_cast を使用してもできない。


ノート: このセクションの制限に従うと、式が const_cast 操作を使用することでそれ自身の型にキャストしても構わないということだ。


2 つのポインタ型 T1 と T2 について、
T1 が cv1,n T への cv1,n-1 ポインタへの ... cv1,1 ポインタへの cv1,0 ポインタで、
T2 が cv2,n T への cv2,n-1 ポインタへの ... cv2,1 ポインタへの cv2,0 ポインタで、
T が任意の object 型または void 型で、cv1,k と cv2,k の cv 修飾が異なっている場合(異なっていなくても構わない)、T1 型の prvalue は const_cast を使用することで T2 型へ明示的に変換することができる。const_cast のポインタの型は元のオブジェクトを参照する。


2 つの object 型 T1 と T2 について、T1 へのポインタが const_cast を使用することで T2 へのポインタに明示的に変換することができる場合、その後に以下の変換を行うことができる。

  • T1 の lvalue は const_cast のキャストを使用することで T2 の lvalue へ明示的に変換することができる。
  • T1 の glvalue は const_cast のキャストを使用することで T2 の xvalue へ明示的に変換することができる。
  • T2 が class 型である場合、T1 の prvalue は const_cast のキャストを使用することで T2 の xvalue へ明示的に変換することができる。

const_cast への、参照の結果は、元のオブジェクトを参照する。


データメンバへのポインタ、データメンバへの multi-level ポインタ、multi-level mixed ポインタに対する const_cast 呼び出しについて、const_cast のルールは、ポインタに対するルールと同じだ。つまり、メンバへのポインタの "メンバ" という側面は、const_cast によって cv 修飾が追加・削除される場合には無効になる。


null ポインタ値は、出力先の型の null ポインタ値に変換される。null メンバポインタ値は、出力先の型の null メンバポインタ値に変換される。


ノート: const 修飾を取り除く const_cast によって、ポインタ、lvalue、データメンバへのポインタを通じて書き込み操作を行うようなオブジェクトの型へ依存することは、undefined behavior になる可能性がある。


casting away constness と呼ばれるプロセスは以下のルールで定義される。それらのルールにおいて Tn と Xn は型を表す。2つのポインタ型について、

  • X1 は、T1 cv1,1 * ... cv1,N * で、T1 はポインタ型ではない。
  • X1 は、T2 cv2,1 * ... cv2,N * で、T2 はポインタ型ではない。
  • K は min(N, M) である。

X1 から X2 への cast away constness によるキャストは、非ポインタ型 T について

  • T cv1,(N-K+1) * cv1,(N-K+2) * ... cv1,N *

から

  • T cv2,(M-K+1) * cv2,(M-K+2) * ... cv2,M *

への暗黙の変換は存在しない。


T1 型の lvalue から T2 型の lvalue への、lvalue reference キャストを使用することによるキャスト、または T1 型の式から T2 型の xvalue への、rvalue reference キャストを使用することによるキャストは、T1 へのポインタ型の prvalue から T2 へのポインタ型へのキャストが casts away constness である場合は casts away constness である。


T1 型の X のデータメンバへのポインタ型の prvalue から T2 型の Y のデータメンバへのポインタ型へのキャストは、T1 へのポインタ型の prvalue から T2 へのポインタ型へのキャストが casts away constness である場合は casts away constness である。


メンバへの multi-level ポインタと multi-level mixed ポインタとメンバへのポインタについて、メンバへのポインタの "メンバ" という側面は、const の cv 修飾が外される場合には無効になる。


ノート: cv 修飾の変更だけの呼び出しによるいくつかの変換は、const_cast を使用するだけではできない。例えば、ポインタから関数への変換は、そのいくつかの変換が未定義の値を導くため、カバーされない。同じ理由で、ポインタからメンバ関数への変換は、const メンバ関数へのポインタから非 const メンバ関数へのポインタへの変換はカバーされない。

N3092 §5.2.11

知りたかったのは太字のところだけ。lvalue と rvalue が細分化されちゃったので、そっちの定義を調べないと全然理解できない・・・。