是否可以动态定义_Generic的关联列表?

问题描述 投票:2回答:1

我有这样的模板:

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_intfunc_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

c gcc generic-programming c11
1个回答
0
投票

我认为您可以通过可怕的“ 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,没有扩展名。

© www.soinside.com 2019 - 2024. All rights reserved.