gpt4 book ai didi

c++ - 在 gcc 中的不兼容函数类型之间进行转换

转载 作者:行者123 更新时间:2023-11-28 04:14:14 25 4
gpt4 key购买 nike

我有一个代码生成脚本,它是由其他人在 2008 年左右编写的,从那时起几乎没有变化,运行良好。就在最近,我尝试使用 gcc9 进行编译,我在生成的代码中看到了 7300 个关于“在不兼容的函数类型之间进行转换”的警告。

该代码采用一组函数指针和各种类型标识符,并将所有内容插入到一个大映射中,稍后用于选项序列化、打印等。许多函数和变量被强制转换并存储为某种形式的 void *。否则代码编译没有错误并且工作正常。

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

这是生成警告的示例行:

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);

最佳答案

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

答案是没有正确的方法。这个警告是绝对有道理的。

关键是你有一个类型安全的函数,你可以只传递 filename_t 并将它转换为可以接受任何东西的东西。不遇到未定义行为的唯一方法是仍然向它传递 filename_t,即使您现在可以传递任何其他内容。

这会产生一个问题,即为什么需要将其转换为泛型类型?您说这些函数存储在具有某些类型标识符的映射中。现在,由于信息有限,很难对此做出判断,但对我来说,这听起来有点像人为地构建一种机制来为您选择正确的函数,而为此有一个完美的内置机制:函数重载决议。

因此,在代码中的某个时刻,您手边必须有一个 filename_t 对象。然后(我假设)您从中推断出一些类型标识符并使​​用它来查找映射中的正确函数。然后你将你的 filename_t 作为 void* 传递到那里,知道它会起作用。

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

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

关于c++ - 在 gcc 中的不兼容函数类型之间进行转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57014469/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com