汎用選択 (C11)

_Generic キーワードを使用して、コンパイル時に引数の型に基づいて式を選択するコードを記述します。 これは、呼び出される関数が引数の型に応じて選択される、C++ のオーバーローディングに似ています。 この場合、評価する式は引数の型に応じて選択されます。

たとえば、式 _Generic(42, int: "integer", char: "character", default: "unknown"); では 42 の型を評価し、リスト内で一致する型 int を検索します。 これを検出し、"integer" を返します。

構文

generic-selection:
_Generic(assignment-expression, assoc-list)

assoc-list:
association
assoc-list, association

association:
type-name : assignment-expression
default : assignment-expression

最初の assignment-expression は、制御式と呼ばれます。 制御式の型はコンパイル時に決まり、 assoc-list に対して照合され、評価して返す式を検索します。 制御式は評価されません。 たとえば、_Generic(intFunc(), int: "integer", default: "error"); では、intFunc の実行時に呼び出しは行われません。

制御式の型が決まったら、constvolatile および restrictassoc-list と照合される前に削除されます。

選択されていない assoc-list のエントリは評価されません。

制約

  • assoc-list では、同じ型を複数回指定することはできません。
  • assoc-list では、列挙型やその列挙型の基になる型など、相互に互換性のある型を指定することはできません。
  • 汎用選択に既定値がない場合、制御式の汎用結合リストには、互換性のある型名が 1 つだけ含まれている必要があります。

_Generic を使用する 1 つの方法は、マクロです。 <tgmath.h> ヘッダー ファイルでは _Generic を使用して、引数の型に応じた適切な数値演算関数が呼び出されます。 たとえば、cos のマクロでは、float を持つ呼び出しを cosf にマップし、複雑な double を持つ呼び出しを ccos にマップします。

次の例は、渡される引数の型を識別するマクロを記述する方法を示します。 assoc-list のエントリが制御式に一致しない場合、"unknown" が生成されます。

// Compile with /std:c11

#include <stdio.h>

/* Get a type name string for the argument x */
#define TYPE_NAME(X) _Generic((X), \
      int: "int", \
      char: "char", \
      double: "double", \
      default: "unknown")

int main()
{
    printf("Type name: %s\n", TYPE_NAME(42.42));

    // The following would result in a compile error because 
    // 42.4 is a double, doesn't match anything in the list, 
    // and there is no default.
    // _Generic(42.4, int: "integer", char: "character"));
}

/* Output:
Type name: double
*/

必要条件

/std:c11 を使ってコンパイルします。

Windows SDK バージョン 10.0.20348.0 (バージョン 2104) 以降。 最新の SDK のダウンロードするには、「Windows SDK」を参照してください。 C11 および C17 開発用 SDK をインストールして使用する手順については、「C11 と C17 のサポートを Visual Studio にインストールする」を参照してください。

関連項目

/std (言語の標準バージョンの指定)
ジェネリック型数値演算