【问题标题】:C - Method overloading with different struct type arguments using macroC - 使用宏使用不同结构类型参数的方法重载
【发布时间】:2020-04-14 14:27:34
【问题描述】:

我正在尝试在 C 中实现方法重载,最好使用宏,以便标头/库可以处理定义和声明,而不是将其交给用户。现在我已经阅读了这个answer 关于使用_Generic 但是问题是我的函数有struct 类型。所以没有办法使用_Generic__typeof__ 来评估他们的类型。我想知道有没有什么办法。

这就是我的头文件的样子(这是我们应该关心的全部)-

#pragma once

// Macros for generic like use of the data structure

// Macros for the stack type itself
/*
 * Define stack with corresponding type
 * Converts Stack(int) to intstack_t
*/
#define Stack(type) type stack_t

// Macros for functions
/*
 * Define createStack function
 * Converts createStack(int, 5) to create_intstack(5)
*/
#define createStack(type, capacity) create_ ##type ##stack(capacity)

/*
 * Define destroyStack function
 * Converts destroyStack(someIntStack) to destroy_intstack(someIntStack)
 * Where someIntStack is a pointer to a variable of type intstack_t
*/
#define destroyStack(stack) _Generic(stack, intstack_t*: destroy_intstack, charstack_t*: destroy_charstack)(stack)

/*
 * Define push function
 * Converts push(someIntStack, data) to intstack_push(someIntStack, data)
 * Where someIntStack is a pointer to a variable of type intstack_t
*/
#define push(stack, data) _Generic(stack, intstack_t*: intstack_push, charstack_t*: charstack_push)(stack, data)

// Stack structure definition(s)

// int stack definition
typedef struct IntegerStack {
    int top;
    unsigned capacity;
    int* arr;
}intstack_t;

// char stack definition
typedef struct CharacterStack {
    int top;
    unsigned capacity;
    char* arr;
}charstack_t;

//Stack functions

// int stack functions
intstack_t* create_intstack(int);
void destroy_intstack(intstack_t*);
void intstack_push(intstack_t*, int);

// char stack functions
charstack_t* create_charstack(int);
void destroy_charstack(charstack_t*);
void charstack_push(charstack_t*, char);

大部分函数声明(以及它们各自的宏)已被删除,因为它们的功能基本相同。我只关心提供的push 函数宏。其他宏确实可以显示我想要什么样的用例。显然,push 中使用的宏使用 _Generic 将无法工作,因为 intstack_tcharstack_t 不是原始类型。

目标是让用户能够使用push(stack, data),其中堆栈可以是intstack_t*charstack_t* 类型的变量,而push(stack, data) 语句将转换为intstack_push(stack, data) 或@987654337 @分别。

【问题讨论】:

  • 这可能是可能的,但它可能会使您的代码难以阅读和维护。
  • 不使用类型,而是使用void * 并存储指向不透明类型的指针。
  • 我真的不想使用 void 指针,因为它可能会使代码类型不安全并引发严重的漏洞。我对难以阅读/维护的代码很好,但我不希望它不安全,除非明确需要
  • 您在_Generic 调用中省略了控制表达式。我假设您的意思是(stack)。但是为什么类型不是原始类型很重要?
  • @rici 我的错,我没有注意到我缺少参数。但它不适用于“intstack_t”或“charstack_t”类型,因为_Generic 不允许这些类型,它只允许像intlong 等基本类型

标签: c struct macros c-preprocessor


【解决方案1】:

_Generic 将适用于可变长度数组以外的任何完整类型。尽管您不能将不完整类型与 _Generic 调用中的值相关联,但指向不完整类型的指针没有问题。

因此,您的 push 宏可以正常工作,即使在 instack_tcharstack_t 不透明的上下文中使用也是如此。

大肠杆菌样本:http://coliru.stacked-crooked.com/a/7d9b181af2429c5e

【讨论】:

  • 奇怪,似乎只有 Visual Studio clang 工具会抛出错误,当我直接从命令行使用 clang 时,它似乎可以工作。谢谢!
猜你喜欢
  • 1970-01-01
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2020-06-02
  • 1970-01-01
  • 2014-10-10
  • 2012-07-17
  • 2013-09-28
相关资源
最近更新 更多