我是 C 新手,目前正在通過在 C11 中使用 _Generic 探索函式多載的概念。
在這篇 SO post 中,@Lundin 提供了以下代碼片段,我運行起來沒有任何問題:
#include <stdio.h>
void func_int (int x) { printf("%d\n", x); }
void func_char (char ch) { printf("%c\n", ch); }
#define func(param) \
_Generic((param), \
int: func_int(param), \
char: func_char(param)); \
int main()
{
func(1);
func((char){'A'});
}
@Lundin 還提到了以下內容:
更好的方法是使用單個結構引數創建一個函式介面,該引數可以調整為包含所有必要的引數。有了這樣的介面,你就可以使用上面基于_Generic的簡單方法了。型別安全且可維護。
所以我決定擴展上面的例子structs來看看它的實際效果。
以下是我的嘗試:
#include <stdlib.h>
#include <stdio.h>
typedef struct args_int Args_int;
typedef struct args_char Args_char;
void func_int(Args_int args);
void func_char(Args_char args);
struct args_int {
int val;
};
struct args_char {
char val;
};
#define func(param)\
_Generic((param),\
Args_int: func_int(param),\
Args_char: func_char(param));
void func_int (Args_int args) {
printf("%d\n", args.val);
}
void func_char (Args_char args) {
printf("%c\n", args.val);
}
int main(void) {
Args_char args = {0};
args.val = 'A';
func(args);
}
However, unfortunately, I get the following compilation error, which complains that I've passed in an Args_char when the compiler is expecting an Args_int. Clearly, my intent is to pass an Args_char and my expectation is for func_char to be called as a result.
struct_args_by_val_executable.c:35:10: error: passing 'Args_char' (aka 'struct args_char') to parameter of incompatible type 'Args_int' (aka 'struct args_int')
func(args);
^~~~
struct_args_by_val_executable.c:20:28: note: expanded from macro 'func'
Args_int: func_int(param),\
^~~~~
struct_args_by_val_executable.c:24:25: note: passing argument to parameter 'args' here
void func_int (Args_int args) {
^
1 error generated.
Why isn't my example working as expected and what is the fix here?
On a related note, I managed to get a "pointer to a struct" version working without any issues as shown below. However, given the above compilation error, I feel as though this may have been a fluke?
#include <stdio.h>
typedef struct args_int Args_int;
typedef struct args_char Args_char;
void func_int(Args_int *args);
void func_char(Args_char *args);
struct args_int {
int val;
};
struct args_char {
char val;
};
#define func(param)\
_Generic((param),\
Args_int*: func_int(param),\
Args_char*: func_char(param));
void func_int (Args_int *args) {
printf("%d\n", args->val);
}
void func_char (Args_char *args) {
printf("%c\n", args->val);
}
int main(void) {
Args_char args = {0};
args.val = 'A';
func(&args);
}
The output to the above is as expected:
A
uj5u.com熱心網友回復:
問題是所有使用的運算式都_Generic必須是有效的。在您的示例中,宏func擴展為:
int main(void) {
Args_char args = {0};
args.val = 'A';
_Generic(args,
Args_int: func_int(args),
Args_char: func_char(args));
}
請注意,使用func_int(args)for argswhichArgs_char會導致錯誤。
解決方案是使用_Generic選擇一個函式指標,然后對其應用引數。
#define func(param) \
_Generic((param), \
Args_int: func_int, \
Args_char: func_char) (param)
uj5u.com熱心網友回復:
只是張貼這個“記錄”:
這實際上不是你在那里找到的一個很好的我的代碼示例!_Generic正如@tstanisl 剛剛在他們的回答中提到的那樣,將引數串列包含在子句之外會更好(我會接受這個作為您問題的答案)。這就是 C 委員會甚至打算使用該功能的方式,您可以在標準本身中找到這樣的示例,參見示例 6.5.1:
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
您找到的代碼片段很幸運,因為char它int可以在呼叫函式時“就像通過賦值一樣”相互轉換。當使用兩個不能被隱式轉換的不兼容型別時,宏會為錯誤的型別錯誤地擴展。
我現在更新了https://stackoverflow.com/a/44633838/584518來使用這個:
#define func(param) \
_Generic((param), \
int: func_int, \
char: func_char)(param) \
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/311188.html
標籤:c generics struct overloading
上一篇:通用擴展方法型別推斷
