C++ C相当于C++;脱模

C++ C相当于C++;脱模,c++,c,macros,decltype,C++,C,Macros,Decltype,在我的C项目中,有一个由另一位同事创建的结构,其中包含一些函数指针: struct tools { int (*tool_a) (int, int, int); ... }; 我无权更改此结构和相关文件。 现在我正在使用结构进行编码。 我必须定义一个函数,其返回类型和参数列表必须与tools.tool\u a 这意味着我的功能必须如下: int my_func(int, int, int); 问题是结构变化很大,尤其是返回类型,例如int今天被size\t替换,所以我不得

在我的C项目中,有一个由另一位同事创建的结构,其中包含一些函数指针:

struct tools {  
    int (*tool_a) (int, int, int);
    ...
};

我无权更改此结构和相关文件。

现在我正在使用结构进行编码。
我必须定义一个函数,其返回类型和参数列表必须与
tools.tool\u a

这意味着我的功能必须如下:

int my_func(int, int, int);
问题是结构变化很大,尤其是返回类型,例如
int
今天被
size\t
替换,所以我不得不对代码进行大量修改。

< >我知道C++中的代码> DECKEXT/<代码>可以帮助我,所以我只想知道C是否有等价的东西? 我想我可以使用宏,但我不知道如何使用,我甚至不知道这是否可行。

真实案例 我正在用C为linux内核开发一些测试工具。
在我的公司里,有许多来自其他团体的定制内核版本。出于历史原因,其中一些使用
int
,其他使用
size\u t
ssize\u t
等等。

现在当我编码时,我必须这样做:

// int my_func(int a, int b, int c)
size_t my_func(int a, int b, int c)
// ssize_t my_func(int a, int b, int c)
{}
struct tools my_tool = {
    .tool_a = my_func;
}

我必须不断地注释和取消注释…

好吧,这不是
decltype
,但如果你能说服你的同事使用类型别名,你就可以进行静态类型检查了

如果您的同事可以被说服这样做:

typedef int tool_a_prototype(int, int, int);

struct tools {  
    tool_a_prototype *tool_a;
};
然后您可以这样声明您的函数:

tool_a_prototype my_tool_a;

int my_tool_a(int a, int b, int c) {
  //Whatever
}

友好的编译器会告诉您是否存在原型不匹配。

明智的解决方案是强制执行
typedef
。如果这是不可能的,并且函数可能具有的可选类型的数量是有限的,那么您可以使用C11
\u Generic
编写一些东西

不要使用一个名为
my_func
的函数,而是使用不同的名称创建多个函数。根据返回类型为其名称加前缀。然后有一个宏,根据传递的类型,该宏又会重新定向到相应的函数

例如:

#include <stdio.h>

/*** the struct that cannot be changed ***/
struct tools {  
    int (*tool_a) (int, int, int);
};

/*** any number of functions with different types ***/
int int_my_func(int a, int b, int c) 
{ 
  puts(__func__); 
}

size_t size_t_my_func(int a, int b, int c) 
{ 
  puts(__func__); 
}

/*** macro to select the appropriate function based on type ***/
#define my_func_typeof(type)                           \
  _Generic( (type),                                    \
            int(*)(int,int,int)    : int_my_func,      \
            size_t(*)(int,int,int) : size_t_my_func)

/*** caller code ***/
int main (void)
{
  struct tools my_tool = {
    .tool_a = my_func_typeof( (struct tools){0}.tool_a )
  };

  my_tool.tool_a(1,2,3);

}
#包括
/***无法更改的结构***/
结构工具{
int(*工具a)(int,int,int);
};
/***具有不同类型的任意数量的函数***/
int_my_func(int a,int b,int c)
{ 
puts(函数);
}
大小\u t大小\u t\u我的函数(整数a、整数b、整数c)
{ 
puts(函数);
}
/***宏以根据类型选择适当的函数***/
#定义我的函数类型(类型)\
_泛型((类型)\
int(*)(int,int,int):int_my_func\
大小(int,int,int):大小(myfunc)
/***呼叫方代码***/
内部主(空)
{
结构工具我的工具={
.tool_a=my_func_typeof((结构工具){0}.tool_a)
};
我的工具。工具a(1,2,3);
}
在这里,我使用一个复合文本
(struct tools){0}.tool_a
来创建一个与
tool_a
类型相同的虚拟对象,然后将其传递给选择适当函数的宏。如果不支持该类型,将出现编译器错误,因为找不到匹配的泛型关联

问题是结构变化很大,尤其是返回 类型,例如int现在被size\u t替换,所以我必须 我的代码改变了很多

<>我知道C++中的DeCype可以帮助我,所以我只想知道C 你有同等的东西吗

如果您愿意使用非标准的gcc扩展,您可以使用:


“我无权更改此结构,但该结构变化很大。”这有什么意义?简单地强制使用Type,如果人们在改变代码,记住,在C,工具> /Cord>是一个数据类型,而不是一个变量,你可以使用成员访问操作符来处理它。顺便说一下,尽管你正在寻找一个C++等价的工具,但我认为它并不真正地保证C++标签。所以,您有
1..N
组为您提供代码,您希望对这些
N
代码运行相同的测试。每次从组
x
获取代码时,签名都相同,但从组
y
获取代码时,签名可能不同。也许您可以为每个组定义一个唯一的符号,并将编译过程更改为包含此符号,如
makegroup=x
。然后剩下的就是一个预处理器条件,它根据
值启用不同的函数签名。@Yves我明白了。然后我想我想出了一个解决办法,请看下面我的答案。我重新编辑了我的问题。嗯,我现在就去试试D@Yves-我希望有帮助。然而,我不确定它是否能回答这个问题。您想进行类型检查,还是不需要注释/取消注释?完全正确。我只想停止评论/取消评论。你看,我昨天开发了我的工具,今天很多同事都在使用它。但是他们正在测试不同的版本。。。所以我必须对第一组使用
int
,对第二组使用
size\u t
。。。这真的很无聊……不管怎样,你的回答帮助很大D至少我可以给我的领导写一份报告…@AjayBrahmakshatriya-我个人认为
size\u t
int
都应该用一个类型别名来抽象。然后,函数体将至少只包含对别名的强制转换。不管怎样,这都是令人讨厌的生意。是的,我总是忘记一般的选择。这应该是公认的答案。@StoryTeller不过,typedef版本是最正确的。这样的代码是最后的选择。很好的解决方案。我有点困惑,为什么在宏的函数名中需要
##
…使用
typedef
有什么好处?如果
typedef
的定义不同,则函数的定义仍需更改。@Gerhardh实际上根本不需要
,它是一个rema
struct tools {  
    int (*tool_a) (int, int, int);
};

typedef typeof( ((struct tools*)NULL)->tool_a ) tool_a_type;
typedef typeof( ((tool_a_type)NULL)(0,0,0) ) tool_a_return_type;

tool_a_return_type my_func(int x, int y, int z)
{

}

struct tools my_tool = {
    .tool_a = my_func
};