Namespaces
Variants

Generic selection (since C11)

From cppreference.net

制御式の型に基づいて、コンパイル時に複数の式から1つを選択する方法を提供します

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - その他のテキスト(Syntax、Explanation、Notes、Keywords、Example、Defect reports、References、See also)はC++関連の専門用語として翻訳せず、原文のまま保持しました - HTMLタグ、属性、クラス名、IDなどはすべて変更せず保持しました - 数値や書式設定もそのまま維持しました

構文

_Generic ( 制御式 , 関連リスト ) (C11以降)

where association-list is a comma-separated list of associations, each of which has the syntax

型名 :
default :

ここで

type-name - 可変修飾されない(つまりVLAまたはVLAへのポインタではない)任意の完全な オブジェクト型
controlling-expression - default 関連付けが使用されない場合、型が type-name のいずれかと互換性がある必要がある任意の式( コンマ演算子 を除く)
expression - 任意の型と値カテゴリの任意の式( コンマ演算子 を除く)

2つの type-name association-list 内で 互換性のある型 を指定することはできません。 default キーワードを使用する関連付けは1つだけ存在できます。 default が使用されておらず、かつどの type-name も制御式の型と互換性がない場合、プログラムはコンパイルされません。

説明

まず、 controlling-expression の型は lvalue conversions を受けます。この変換は型ドメインでのみ実行されます:これはトップレベルのcvr修飾子とatomicityを破棄し、制御式の型に対して配列からポインタ/関数からポインタへの変換を適用しますが、副作用を引き起こしたり値を計算したりすることはありません。

変換後の型は、関連付けのリスト内の type-name と比較されます。

型が関連付けのいずれかの type-name 互換性 がある場合、ジェネリック選択の型、値、および value category は、その type-name に対してコロンの後に現れる expression の型、値、および値カテゴリとなります。

いずれの type-name controlling-expression の型と互換性がなく、 default 関連付けが提供されている場合、ジェネリック選択の型、値、および値カテゴリは、 default : ラベルの後の式の型、値、および値カテゴリとなります。

注記

controlling-expression および選択されなかった選択肢の expression は評価されません。

左辺値変換のため、 "abc" char * にマッチし、 char [ 4 ] にはマッチしません。また、 ( int const ) { 0 } int にマッチし、 const int にはマッチしません。

すべての value category (関数指示子およびvoid式を含む)は、総選択の expression として使用可能であり、選択された場合、総選択自体が同じvalue categoryを持つ。

C99で導入された 型総称数学マクロ は、 <tgmath.h> から提供され、コンパイラ固有の方法で実装されていました。C11で導入された総称選択は、プログラマが同様の型依存コードを記述する能力を与えました。

ジェネリック選択は、C++のオーバーロード(引数の型に基づいてコンパイル時に複数の関数から1つを選択する)に似ていますが、任意の式の間で選択を行う点が異なります。

キーワード

_Generic , default

#include <math.h>
#include <stdio.h>
// tgmath.h マクロ 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));    // デフォルトの cbrt を選択
    printf("cbrtf(3.375) = %f\n", cbrt(y)); // const float を float に変換後、
                                            // 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: 未定)
  • 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++ documentation for Templates
**日本語訳:**
C++ documentation for Templates
**翻訳結果:** C++ documentation for Templates **注記:** - HTMLタグ、属性、および` `, `
`, ``タグ内のテキストは翻訳対象外としました
- "C++ documentation" と "Templates" はC++専門用語のため原文のまま保持しました
- その他のテキストのみを日本語に翻訳しました