基於多個引數的通用選擇

如果需要對型別泛型表示式的多個引數進行選擇,並且所討論的所有型別都是算術型別,則避免巢狀 _Generic 表示式的簡單方法是使用控制表示式中的引數的新增:

int max_int(int, int);
unsigned max_unsigned(unsigned, unsigned);
double max_double(double, double);

#define MAX(X, Y) _Generic((X)+(Y),                \
                           int:      max_int,      \
                           unsigned: max_unsigned, \
                           default:  max_double)   \
                    ((X), (Y))

這裡,控制表示式 (X)+(Y) 僅根據其型別進行檢查而不進行評估。執行算術運算元的常規轉換以確定所選型別。

對於更復雜的情況,可以通過將它們巢狀在一起來基於操作符的多個引數進行選擇。

此示例在四個外部實現的函式之間進行選擇,這兩個函式採用兩個 int 和/或字串引數的組合,並返回它們的總和。

int AddIntInt(int a, int b);
int AddIntStr(int a, const char* b);
int AddStrInt(const char*  a, int b );
int AddStrStr(const char*  a, const char*  b);

#define AddStr(y)                            \
   _Generic((y),         int: AddStrInt,     \
                        char*: AddStrStr,    \
                  const char*: AddStrStr )

#define AddInt(y)                            \
   _Generic((y),          int: AddIntInt,    \
                        char*: AddIntStr,    \
                  const char*: AddIntStr )

#define Add(x, y)                            \
   _Generic((x) ,        int: AddInt(y) ,    \
                       char*: AddStr(y) ,    \
                 const char*: AddStr(y))     \
                         ((x), (y))

int main( void )
{
    int result = 0;
    result = Add( 100 , 999 );
    result = Add( 100 , "999" );
    result = Add( "100" , 999 );
    result = Add( "100" , "999" );

    const int a = -123;
    char b[] = "4321";
    result = Add( a , b );

    int c = 1;
    const char d[] = "0";
    result = Add( d , ++c );
}

即使看起來好像引數 y 被評估不止一次,它也不是 1 。兩個引數僅在巨集 Add:( x , y ) 的末尾進行一次計算,就像在普通的函式呼叫中一樣。

1 (引用自:ISO:IEC 9899:201X 6.5.1.1 通用選擇 3)
不評估通用選擇的控制表示式。