総称選択 (C11以降)
制御式の型に基づいて、コンパイル時に複数の式の中から一つを選択する方法を提供します。
目次 |
[編集] 構文
_Generic ( 制御式 , 関連リスト ) |
(C11 以降) | ||||||||
ここで、関連リスト はカンマで区切られた関連のリストであり、それぞれの関連は以下の構文を持ちます。
型名 : 式 |
|||||||||
default : 式 |
|||||||||
ここで、
| 型名 | - | 可変修飾されていない(つまり、VLAでもVLAへのポインタでもない)完全なオブジェクト型。 |
| 制御式 | - | default 関連が使用されない場合、その型が 型名 のいずれかと互換性がある必要がある、任意の式(カンマ演算子を除く)。 |
| 式 | - | 任意の型と値カテゴリを持つ任意の式(カンマ演算子を除く)。 |
関連リスト 内の2つの 型名 が互換性のある型を指定してはなりません。default キーワードを使用する関連は1つだけです。default が使用されず、かつ 型名 のいずれも制御式の型と互換性がない場合、プログラムはコンパイルされません。
[編集] 説明
まず、制御式 の型は左辺値変換を受けます。この変換は型領域のみで行われ、トップレベルのcvr-qualifierとアトミック性を破棄し、制御式の型に配列からポインタへの変換/関数からポインタへの変換を適用しますが、いかなる副作用も引き起こさず、いかなる値も計算しません。
変換後の型は、関連のリストから取得した 型名 と比較されます。
型が関連のいずれかの 型名 と互換性がある場合、総称選択の型、値、および値カテゴリは、その 型名 の後にコロンで示される 式 の型、値、および値カテゴリになります。
型名 のいずれも 制御式 の型と互換性がなく、かつ default 関連が提供されている場合、総称選択の型、値、および値カテゴリは、default : ラベルの後に続く式の型、値、および値カテゴリになります。
[編集] 注釈
制御式 および選択されなかった選択肢の 式 は、決して評価されません。
左辺値変換のため、"abc" は char* と一致し、char[4] とは一致しません。また、(int const){0} は int と一致し、const int とは一致しません。
関数指示子やvoid式を含むすべての値カテゴリは、総称選択の 式 として許可されており、選択された場合、総称選択自体も同じ値カテゴリを持ちます。
C99で導入された<tgmath.h>の型総称算術マクロは、コンパイラ固有の方法で実装されていました。C11で導入された総称選択により、プログラマは同様の型依存コードを書くことができるようになりました。
総称選択はC++のオーバーロード(引数の型に基づいてコンパイル時に複数の関数の中から1つが選択される)に似ていますが、任意の式の間で選択を行う点が異なります。
[編集] キーワード
[編集] 例
#include <math.h> #include <stdio.h> // Possible implementation of the tgmath.h macro cbrt #define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \ )(X) int main(void) { double x = 8.0; const float y = 3.375; printf("cbrt(8.0) = %f\n", cbrt(x)); // selects the default cbrt printf("cbrtf(3.375) = %f\n", cbrt(y)); // converts const float to float, // then selects cbrtf }
出力
cbrt(8.0) = 2.000000 cbrtf(3.375) = 1.500000
[編集] 欠陥レポート
以下の動作変更を伴う欠陥報告が、以前に発行されたC規格に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| DR 481 | C11 | 制御式が左辺値変換を受けるかどうかが不明確だった | 受ける |
[編集] 参照
- C23標準 (ISO/IEC 9899:2024)
- 6.5.1.1 総称選択 (p: TBD)
- C17標準 (ISO/IEC 9899:2018)
- 6.5.1.1 総称選択 (p: 56-57)
- C11標準 (ISO/IEC 9899:2011)
- 6.5.1.1 総称選択 (p: 78-79)
[編集] 関連項目
| C++ドキュメント - テンプレート
|