総称選択
制御式の型に基づいてコンパイル時に複数の式からひとつを選択する方法を提供します。
目次 |
[編集]構文
_Generic ( controlling-expression, association-list) | (C11以上) | ||||||||
ただし association-list はコンマ区切りの関連リストで、それぞれの関連は以下の構文を持ちます。
type-name: expression | |||||||||
default : expression | |||||||||
ただし
type-name | - | 可変修飾でない (つまり、 VLA または VLA へのポインタでない) 任意の完全オブジェクト型。 |
controlling-expression | - | 任意の式 (コンマ演算子は除きます)。 default 関連が使用されない場合は、 type-name のいずれかと互換な型でなければなりません。 |
expression | - | 任意の型および値カテゴリの任意の式 (コンマ演算子は除きます)。 |
association-list 内の複数の type-name が互換な型を表してはなりません。 キーワード default
を使用する関連がひとつのみ存在しても構いません。 default
が使用されず、 type-name のいずれも制御式の型と互換でない場合、プログラムはコンパイルできません。
[編集]説明
まず、 controlling-expression の型に対して左辺値変換が行われます。 変換は型の領域でのみ行われます。 いかなる副作用も値計算も開始することなく、トップレベルの cvr 修飾およびアトミック性が破棄され、制御式の型への配列からポインタおよび関数からポインタへの変換が適用されます。
変換後の型が関連リストの type-name と比較されます。
型が関連のいずれかの type-name と互換であれば、総称選択の型、値、および値カテゴリは、その type-name のコロンの後に現れる expression の型、値、および値カテゴリになります。
controlling-expression の型が type-name のいずれとも互換でなく、 default
関連が提供されていれば、総称選択の型、値、値カテゴリは、 default :
ラベルの後の式の型、値、および値カテゴリになります。
[編集]ノート
総称選択の controlling-expression および選択されなかった expression は評価されることはありません。
左辺値変換のため、 "abc" は char[4] ではなく char* にマッチし、 (intconst){0} は constint ではなく int にマッチします。 これは C17 DR 481 によって規定されました (遡及的に C11 にも適用されます)。
総称選択の expression として、すべての値カテゴリ (関数指示子および void 式を含みます) が使用でき、選択された場合、総称選択自身はその同じ値カテゴリを持ちます。
C99 で導入された <tgmath.h>
の型総称数学マクロはコンパイラ固有の方法で実装されていました。 C11 で導入された総称選択は同様の型依存なコードを書く能力をプログラマに与えました。
総称選択は C++ のオーバーロード (実引数の型に基づいて複数の関数のうちのひとつがコンパイル時に選択される機能) に似ていますが、総称選択は任意の式による選択を可能にします。
[編集]キーワード
[編集]例
#include <stdio.h>#include <math.h> // <tgmath.h> のマクロ cbrt の実装例#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \ )(X) int main(void){double x =8.0;constfloat y =3.375;printf("cbrt(8.0) = %f\n", cbrt(x));// デフォルトの cbrt が選択されます。printf("cbrtf(3.375) = %f\n", cbrt(y));// const float が float に変換され、// cbrtf が選択されます。}
出力:
cbrt(8.0) = 2.000000 cbrtf(3.375) = 1.500000
[編集]参考文献
- C11 standard (ISO/IEC 9899:2011):
- 6.5.1.1 Generic selection (p: 78-79)