我有一个代码生成脚本,它是由其他人在2008年左右编写的,并且运行良好,从那以后基本没有变化。就在最近,我尝试用gcc9编译,并在生成的代码中看到了7300条关于“在不兼容函数类型之间进行转换”的警告。
该代码接受一组函数指针和各种类型标识符,并将所有内容插入到稍后用于选项序列化、打印等的大映射中。许多函数和变量作为某种形式的void *进行转换和存储。否则,代码编译时不会出现错误,并且工作正常。
我尝试了各种C样式的强制转换( reinterpret_cast ),并将函数指针转换为void(*)(void),但它们都没有删除警告。将函数转换为泛型类型以避免此警告的正确方法是什么?我唯一能想到的解决方案是禁用-Wcast-function。
下面是一个生成警告的示例行:
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);该警告与以下两项功能有关:
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中间插入的类。
注意,有几十个不同的str_from_***()函数,它们有不同的类作为参数。
我得到的警告是:
../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);发布于 2019-07-12 23:12:49
将函数转换为泛型类型的正确方法是什么?
答案是没有正确的方法。这一警告是绝对合理的。
关键是,您有一个typesafe函数,您只能传递filename_t,并将它转换为可以从字面上获取任何内容的东西。避免遇到未定义的bahavior的唯一方法是仍然传递一个filename_t,即使您现在可以传递其他任何东西。
这就产生了为什么需要将其转换为泛型类型的问题?您说这些函数存储在带有某种类型标识符的映射中。现在,由于信息有限,很难对此做出判断,但在我看来,这听起来有点像人工构建一种为您选择正确功能的机制,而在这方面有一个完美的内置机制:函数过载解决机制。
因此,在代码的某个时候,您必须手头上有一个filename_t对象。然后(我假设)从它推断出某种类型标识符,并使用它在地图中查找适当的函数。然后将您的filename_t作为一个void*传递到那里,因为您知道它会工作。
我确信它比这个要复杂得多,但也许您可以识别这部分逻辑并消除它:去掉映射(至少是将标识符映射到函数的部分),然后在您仍然知道类型的时候直接调用该函数(因为重载解析将对您起作用)。
模板可以帮助您保留类型,而不是使所有的void*。
https://stackoverflow.com/questions/57014469
复制相似问题