我有这样的模板:
template.h
----------
// Declare a function "func_type()"
void JOIN(func_, T)(T t) { return; }
#undef T
我这样使用,以便针对不同类型生成相同的功能:
example.c
---------
#define T int
#include "template.h"
#define T float
#include "template.h"
我想使用一个func
来代替funct_int
,func_float
等。我对_Generic
的问题是,似乎不可能动态定义关联列表。实际上,我想要这样的东西:
#define func(TYPE) _Generic((TYPE), AUTO_GENERATED_LIST)
而不是像这样手动定义每个新类型:
#define func(TYPE) _Generic((TYPE), int: func_int..., float: func_float...)
这是不起作用的代码示例:https://ideone.com/HN7sst
我认为您可以通过可怕的“ X宏”来实现。创建一个列表,例如
#define SUPPORTED_TYPES(X) \
X(int, "%d") \
X(float, "%f") \
其中int
是类型,在这种情况下,我将printf格式说明符用作另一项。这些可以算作有效的预处理器令牌。
然后您可以通过这样的邪恶宏生成所有函数:
#define DECLARE_F(type, fmt) \
void f_##type (type param) \
{ printf(fmt "\n", param); }
SUPPORTED_TYPES(DECLARE_F)
这将创建诸如void f_int (int param) { printf("%d\n", param); }
的功能。也就是说,与C ++模板非常相似-函数执行相同的操作但具有不同的类型。
然后您可以像这样编写_Generic宏:
void dummy (void* param){}
#define GENERIC_LIST(type, fmt) type: f_##type,
#define func(x) _Generic((x), SUPPORTED_TYPES(GENERIC_LIST) default: dummy)(x)
这里您定义了通用asoc。使用GENERIC_LIST
项列出type
,但忽略其他所有内容。因此它扩展为例如int: f_int,
。
一个问题是旧的“尾随逗号”问题,我们不能像_Generic((x), int: f_int,)(x)
一样写_Generic,在f_int
之后会弄乱语法。我通过调用一个伪函数的default
子句解决了这个问题,这不理想...可能想将assert
插入该函数中。
完整示例:
#include <stdio.h>
#define SUPPORTED_TYPES(X) \
X(int, "%d") \
X(float, "%f") \
#define DECLARE_F(type, fmt) \
void f_##type (type param) \
{ printf(fmt "\n", param); }
SUPPORTED_TYPES(DECLARE_F)
void dummy (void* param){}
#define GENERIC_LIST(type, fmt) type: f_##type,
#define func(x) _Generic((x), SUPPORTED_TYPES(GENERIC_LIST) default: dummy)(x)
int main (void)
{
int a = 1;
float b = 2.0f;
func(a);
func(b);
}
输出:
1
2.000000
这是100%ISO C,没有扩展名。