?
This document uses PHP Chinese website manual Release
提供了一種在編譯時根據(jù)控制表達式的類型選擇多個表達式之一的方法。
_Generic ( controlling-expression , association-list ) | (since C11) |
---|
其中關(guān)聯(lián)列表是以逗號分隔的關(guān)聯(lián)列表,每個關(guān)聯(lián)列表都有語法。
type-name : expression | ||
---|---|---|
default : expression |
其中
類型名 | - | 任何未經(jīng)可變修改的完整對象類型(即不是VLA或指向VLA的指針)。 |
---|---|---|
控制表達 | - | 如果不使用默認(rèn)關(guān)聯(lián),則其類型必須與其中一個類型名稱兼容的任何表達式(逗號運算符除外) |
表達 | - | 任何類型和值類別的任何表達式(逗號運算符除外) |
關(guān)聯(lián)列表中沒有兩個類型名稱可以指定兼容類型??赡苤挥幸粋€關(guān)聯(lián)使用關(guān)鍵字default
。如果default
沒有使用,并且沒有任何類型名稱與控制表達式的類型兼容,程序?qū)⒉粫幾g。
控制表達式的類型(在適用的情況下應(yīng)用左值轉(zhuǎn)換后(如果支持,請參閱下面的注釋))與關(guān)聯(lián)列表中的類型名稱進行比較。
如果類型與其中一個關(guān)聯(lián)的類型名稱兼容,則泛型選擇的類型,值和值類別是出現(xiàn)在該類型的冒號后面的表達式的類型,值和值類別 - 名稱。
如果沒有任何類型名稱與控制表達式的類型兼容,并且default
提供了關(guān)聯(lián),則泛型選擇的類型,值和值類別是表達式之后的類型,值和值類別該default :
標(biāo)簽。
控制表達式和未選擇的選擇表達式從不被評估。
控制表達式的左值轉(zhuǎn)換仍然是一個未解決的問題(DR 431 / n1930):clang 不執(zhí)行它們并按照原樣使用左值的類型:"abc"
匹配char[4]
而不是char*
,(int const){0}
匹配const int
而不是int
)。同時,gcc執(zhí)行控制表達式的左值轉(zhuǎn)換(僅在類型域中:它放棄了頂級cvr限定符和原子性,或者將數(shù)組應(yīng)用于控制表達式類型的指針/函數(shù)指針轉(zhuǎn)換,而不啟動任何副作用或計算任何值)。對于 GCC,"abc"
匹配char*
和char[4]
和(int const){0}
的比賽int
,而不是const int
。
所有值類別(包括函數(shù)指示符和無效表達式)都可以在通用選擇中作為表達式使用,如果選擇了,則通用選擇本身具有相同的值類別。
<tgmath.h>
在 C99中引入的類型通用數(shù)學(xué)宏以編譯器特定的方式實現(xiàn)。在 C11中引入的通用選擇為程序員提供了編寫類似類型相關(guān)代碼的能力。
泛型選擇類似于C ++中的重載(其中幾個函數(shù)中的一個是在編譯時根據(jù)參數(shù)的類型選擇的),除了它在任意表達式之間進行選擇之外,與函數(shù)重載不同,函數(shù)可能具有不同的返回類型,甚至不同的價值類別。
_Generic
, default
.
#include <stdio.h>#include <math.h> // Possible implementation of the tgmath.h macro cbrt#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \/*for clang*/ const float: cbrtf, \ 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)); // gcc: converts const float to float, // then selects cbrtf // clang: selects cbrtf for const float}
輸出:
cbrt(8.0) = 2.000000cbrtf(3.375) = 1.500000