如何在不复制代码的情况下创建不可转换的 C 类型?
How to create non-convertible C types without duplicating code?
我有一些 C 代码,其中包含各种函数,每个函数都采用不同类型的 "handle" 对象作为参数。所有这些句柄的实现都是相同的(它只是一个带有 void-pointer 和 item-count 的结构),所以只声明一个实现似乎是合乎逻辑的——但我也希望 C 编译器生成一个编译- 当用户将错误类型的句柄传递给函数时出现错误。
我目前的方法使用 typedef
创建各种句柄类型,它用于记录函数应该接受哪种句柄类型,但编译器会自动转换,因此它不会标记类型- 不匹配为错误。有没有推荐的方法来实现这个,不需要为每种类型手动复制我的 handle-struct-declaration?
玩具示例代码如下:
typedef struct _FruitHandle {
int _numItems;
void * _items;
} FruitHandle;
typedef FruitHandle AppleHandle;
typedef FruitHandle BananaHandle;
// imagine a number of other fruits as well
void EatAnApple(AppleHandle a) {}
void EatABanana(BananaHandle b) {}
// and so on -- each function should ONLY except its own fruit-handle-type as an argument!
int main(int argc, char ** argv)
{
AppleHandle apple;
BananaHandle banana;
EatAnApple(apple); // ok -- types match
EatABanana(banana); // ok -- types match
EatAnApple(banana); // type mismatch -- I want this to be a compile-time error, but it isn't!
EatABanana(apple); // type mismatch -- I want this to be a compile-time error, but it isn't!
return 0;
}
如评论中所述,您可以使用宏执行此操作:
#define FRUIT(name) typedef struct _##name {\
int _numItems;\
void * _items;\
} name
FRUIT(AppleHandle);
FRUIT(BananaHandle);
扩展为:
typedef struct _AppleHandle { int _numItems; void * _items;} AppleHandle;
typedef struct _BananaHandle { int _numItems; void * _items;} BananaHandle;
您可能会发现 this question 的答案很有帮助。虽然 C 中没有显式类型继承,但您可以使用顶部答案中描述的习惯用法来创建 AppleHandle 和 BananaHandle。
typedef struct {
int _numItems;
void *_items;
} FruitHandle;
typedef struct {
FruitHandle fruit_handle;
} AppleHandle;
typedef struct {
FruitHandle fruit_handle;
} BananaHandle;
...
我有一些 C 代码,其中包含各种函数,每个函数都采用不同类型的 "handle" 对象作为参数。所有这些句柄的实现都是相同的(它只是一个带有 void-pointer 和 item-count 的结构),所以只声明一个实现似乎是合乎逻辑的——但我也希望 C 编译器生成一个编译- 当用户将错误类型的句柄传递给函数时出现错误。
我目前的方法使用 typedef
创建各种句柄类型,它用于记录函数应该接受哪种句柄类型,但编译器会自动转换,因此它不会标记类型- 不匹配为错误。有没有推荐的方法来实现这个,不需要为每种类型手动复制我的 handle-struct-declaration?
玩具示例代码如下:
typedef struct _FruitHandle {
int _numItems;
void * _items;
} FruitHandle;
typedef FruitHandle AppleHandle;
typedef FruitHandle BananaHandle;
// imagine a number of other fruits as well
void EatAnApple(AppleHandle a) {}
void EatABanana(BananaHandle b) {}
// and so on -- each function should ONLY except its own fruit-handle-type as an argument!
int main(int argc, char ** argv)
{
AppleHandle apple;
BananaHandle banana;
EatAnApple(apple); // ok -- types match
EatABanana(banana); // ok -- types match
EatAnApple(banana); // type mismatch -- I want this to be a compile-time error, but it isn't!
EatABanana(apple); // type mismatch -- I want this to be a compile-time error, but it isn't!
return 0;
}
如评论中所述,您可以使用宏执行此操作:
#define FRUIT(name) typedef struct _##name {\
int _numItems;\
void * _items;\
} name
FRUIT(AppleHandle);
FRUIT(BananaHandle);
扩展为:
typedef struct _AppleHandle { int _numItems; void * _items;} AppleHandle;
typedef struct _BananaHandle { int _numItems; void * _items;} BananaHandle;
您可能会发现 this question 的答案很有帮助。虽然 C 中没有显式类型继承,但您可以使用顶部答案中描述的习惯用法来创建 AppleHandle 和 BananaHandle。
typedef struct {
int _numItems;
void *_items;
} FruitHandle;
typedef struct {
FruitHandle fruit_handle;
} AppleHandle;
typedef struct {
FruitHandle fruit_handle;
} BananaHandle;
...