在gcc中不兼容的函数类型之间进行强制转换 [英] Cast Between Incompatible Function Types in gcc

查看:125
本文介绍了在gcc中不兼容的函数类型之间进行强制转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代码生成脚本,该脚本是在2008年左右由其他人编写的,此后几乎没有发生任何变化.最近,我尝试使用gcc9进行编译,并且在生成的代码中看到7300警告在不兼容的函数类型之间进行转换".

I have a code generation script that was written by someone else around 2008 and has worked fine mostly unchanged since then. Just recently I tried compiling with gcc9 and I see 7300 warnings for "cast between incompatible function types" in the generated code.

该代码采用一组函数指针和各种类型标识符,并将所有内容插入到大映射中,以供以后进行选项序列化,打印等.许多函数和变量都以void *的形式进行转换和存储.否则,该代码可以编译而不会出错,并且可以正常运行.

The code takes a set of function pointers and various type identifiers and inserts everything into a big map that's used later for option serialization, printing, etc. Many functions and variables are cast and stored as some form of void *. The code otherwise compiles with no errors and works properly.

我尝试了各种C风格的强制转换,reinterpret_cast和将函数指针强制转换为void(*)(void),但是它们都没有删除警告.为避免此警告,将函数强制转换为通用类型的正确方法是什么?我唯一能想到的解决方案是禁用-Wcast-function-type.

I tried various C-style casts, reinterpret_cast, and casting the function pointer to void(*)(void), but none of them remove the warnings. What's the correct way to cast the function to a generic type to avoid this warning? The only solution I can come up with is disabling -Wcast-function-type.

以下是生成警告的示例行:

Here is one example line that generates warnings:

pim.must_find("input_fn")->set_introspect_info( sizeof(filename_t), ((char *)(&p_cn->input_fn)) - ((char *)p_cn), 0,invalid_offset, (str_from_base_t *)str_from_filename_t, (send_base_t *)send_filename_t, (recv_base_t *)recv_filename_t, (val_from_param_t *)val_from_param_filename_t, 0);

警告与以下两个功能有关:

The warning is related to these two functions:

typedef std::string str_from_base_t( void const * );

std::string str_from_filename_t( filename_t const & v ) { return v; }

filename_t是从std :: string插入的类.

Where filename_t is a class that interits from std::string.

请注意,有数十种不同的str_from _ ***()函数具有不同的类作为参数.

Note that there are dozens of different str_from_***() functions that have different classes as arguments.

我得到的警告是:

../src/gen/DEFReader_PostParam.cc: In function 'void croix::DEFReaderCLI_introspect_pim_init()':
../src/gen/DEFReader_PostParam.cc:25:153: warning: cast between incompatible function types from 'std::string (*)(const croix::filename_t&)' {aka 'std::basic_string<char> (*)(const croix::filename_t&)'} to 'std::string (*)(const void*)' {aka 'std::basic_string<char> (*)(const void*)'} [-Wcast-function-type]
25 |  pim.must_find("input_fn")->set_introspect_info( sizeof(filename_t), ((char *)(&p_cn->input_fn)) - ((char *)p_cn), 0,invalid_offset, (str_from_base_t *)str_from_filename_t, (send_base_t *)send_filename_t, (recv_base_t *)recv_filename_t, (val_from_param_t *)val_from_param_filename_t, 0);

推荐答案

将函数转换为泛型的正确方法是什么?

What's the correct way to cast the function to a generic type?

答案是没有正确的方法.该警告是完全合理的.

The answer is that there is no correct way. The warning is absolutely justified.

重点是您拥有一个类型安全的函数,该函数只能传递 filename_t ,并将其强制转换为可以实际使用任何东西的东西.不会遇到未定义行为的唯一方法是,即使您现在可以传递其他任何内容,仍然要传递一个 filename_t .

The point is that you have a typesafe function that you can pass only filename_t and you cast it to something that can take literally anything. The only way to not run into undefined bahavior is to still pass it a filename_t even though you now could pass anything else.

这产生了一个问题,为什么您需要将其强制转换为泛型?您说这些函数被存储在带有某些类型标识符的映射中.现在,由于信息有限,很难对此进行判断,但是对我来说,这听起来像是人为地构建了一种机制,可以为您选择合适的功能,而为此目的,有一个完善的内置机制:函数重载解析.

That yields the question of why you need to cast it to a generic type? You say that those functions get stored in a map with some type identifiers. Now, due to limited information it is hard to judge on this, but to me this sounds a little like artificially building a mechanism that choses the right function for you, while there is a perfectly working built in mechanism for this: function overload resolution.

因此,在代码中的某些点上,您必须有一个 filename_t 对象.然后(我假设)您从中推断出一些类型标识符,并使用该类型标识符在映射中查找适当的函数.然后,将 filename_t 作为 void * 传递到此处,知道它会起作用.

So, at some point in the code you must have a filename_t object at hands. Then (I'm assuming) you infer some type identifier from it and use that to look up the proper function in a map. Then you pass your filename_t as a void* there, knowing that it will work.

我敢肯定它比这要复杂得多,但是也许您可以识别出逻辑的这一部分并加以摆脱:摆脱地图(至少将类型标识符映射到函数的那一部分),然后调用在您仍然知道类型的时候直接使用该函数(因为重载解析将为您解决问题).

I'm sure it's much more complex than this, but maybe you can identify this part of the logic and get rid of it: get rid of the map (at least that part that maps type identifiers to functions) and just call the function directly at a time where you still know the type (because then overload resolution will do the trick for you).

模板可以帮助您保留类型,而不是使所有内容都变为 void * .

Templates can help you to keep the types instead of making everything void*.

这篇关于在gcc中不兼容的函数类型之间进行强制转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆