我正在尝试在C中构建伪通用类型。本质上,我正在尝试使用预定义的,受约束的类型列表(Option<T>
)克隆Rust的T
。
很明显,C并不适合于此-我这样做主要是为了了解我可以走多远(与我期望在实际生产代码中使用的东西相对)。为此,任何丑陋的骇客都是公平的游戏。
到目前为止,我为所有提供的类型构建了一组单独的内部类型专用函数。看起来像这样:
标题:
#pragma once
#define ALL_OPTIONS \
OPTION_INSTANCE(option_bool, bool) \
OPTION_INSTANCE(option_double, double) \
OPTION_INSTANCE(option_int, int)
#define OPTION_INSTANCE(name, inner) \
typedef struct { \
bool is_some; \
inner val; \
} name##_t;
ALL_OPTIONS
#undef OPTION_INSTANCE
#define OPTION_INSTANCE(name, inner) \
name##_t name##_some(inner val); \
name##_t name##_none(void); \
bool name##_is_some(name##_t self); \
bool name##_is_none(name##_t self); \
ALL_OPTIONS
#undef OPTION_INSTANCE
实施:
#include "option.h"
#define OPTION_INSTANCE(name, inner) \
name##_t name##_some(inner val) { \
return (name##_t) { \
.is_some = true, \
.val = val, \
}; \
} \
\
name##_t name##_none(void) { \
return (name##_t) { \
.is_some = false, \
}; \
} \
\
bool name##_is_some(name##_t self) { \
return self.is_some; \
} \
\
bool name##_is_none(name##_t self) { \
return !self.is_some; \
}
ALL_OPTIONS
#undef OPTION_INSTANCE
请注意,在我的实际代码中,我为生成的类型定义了更多函数。
这工作得很好,尽管基本上我所做的只是减少实现样板。下一步将是实现option_is_some
(无类型限定),该类型可以接受任何 option_<inner>_t
利用C11泛型,使用手动宏可以做到这一点:
#define option_is_some(self) \
_Generic((self), \
option_bool_t: option_bool_is_some, \
option_double_t: option_double_is_some, \
option_int_t: option_int_is_some, \
)(self)
,但这必然会复制ALL_OPTIONS
中定义的类型列表。我真正想做的是像
#define OPTION_INSTANCE(name, inner) \
name##_t: name##_is_some,
#define option_is_some(self) \
_Generic((self), \
ALL_OPTIONS \
default: false \
)(self)
#undef OPTION_INSTANCE
但是失败了,因为在使用ALL_OPTIONS
时option_is_some
被扩展了(其中OPTION_INSTANCE
是不确定的)。
因此,我正在寻找替代方案。我很乐意使用一种根本不同的方法来定义类型的通用列表(而不是ALL_OPTIONS
hack);但是,我确实想保留以下属性:添加新的受支持内部类型仅需要更改在一个位置。