如何用模板参数或 std::function 替换函数指针?
How to replace a function pointer with a template parameter or a std::function?
我运行一个visualstudio中的sonarlint插件。
我的代码有一个主要问题,如下所示:
_declspec(dllexport) void GetInformation(void (add)(const char* pCarName))
{
add("N3-988");
add("N3-40");
add("N3-41");
add("N3-428");
}
错误是
cpp:S5205 : Replace this function pointer with a template parameter or a "std::function".
如何解决?
错误是转移注意力的错误。您打错了函数指针语法,仅此而已。你需要
void (*add)(const char* pCarName)
作为参数类型。 add
那么就是一个函数指针,在函数体(add("N3-988");
等)中的使用是合适的。
可能像下面这样
#include <cstdio>
template<typename FuncT>
void GetInformation(FuncT func)
{
func("N3-988");
func("N3-40");
func("N3-41");
func("N3-428");
}
int main()
{
auto func = [](const char* s){ printf("%s\n",s); };
GetInformation(func);
}
这不是真正的错误,从某种意义上说,您不能将函数指针用作参数。你可以。出于模糊性、灵活性和性能原因,不鼓励使用函数指针。请参见 https://jira.sonarsource.com/browse/RSPEC-5205。因此,如果您不关心这些注意事项,您可能想要抑制它。
缺乏灵活性意味着您无法传递额外的上下文(除非使用所谓的“thunks”)。可以通过为用户上下文使用额外的 void*
参数来解决这种缺乏灵活性的问题:
_declspec(dllexport) void GetInformation(
void (add)(const char* pCarName, void* context), void* context)
{
add("N3-988", context);
add("N3-40", context);
add("N3-41", context);
add("N3-428", context);
}
您也可以按照建议使用 std::function
,如果您不认为您的 DLL 将具有 C++ 接口(因此将取决于 C++ 运行时):
_declspec(dllexport) void GetInformation(std::function<void (const char*)> add)
{
add("N3-988");
add("N3-40");
add("N3-41");
add("N3-428");
}
请注意,您不能按照建议使用 template
,因为无法使用 __declspec(dllexport)
从 DLL 导出模板。由于避免间接寻址,模板将具有固定性能,但 DLL 接口意味着您无法避免它。
注意函数作为参数:
void GetInformation(void (add)(const char* pCarName))
由于所谓的衰减:
相当于函数指针参数
void GetInformation(void (*add)(const char* pCarName))
建议用一个替换另一个的答案具有误导性,它不会解决任何问题。
我运行一个visualstudio中的sonarlint插件。 我的代码有一个主要问题,如下所示:
_declspec(dllexport) void GetInformation(void (add)(const char* pCarName))
{
add("N3-988");
add("N3-40");
add("N3-41");
add("N3-428");
}
错误是
cpp:S5205 : Replace this function pointer with a template parameter or a "std::function".
如何解决?
错误是转移注意力的错误。您打错了函数指针语法,仅此而已。你需要
void (*add)(const char* pCarName)
作为参数类型。 add
那么就是一个函数指针,在函数体(add("N3-988");
等)中的使用是合适的。
可能像下面这样
#include <cstdio>
template<typename FuncT>
void GetInformation(FuncT func)
{
func("N3-988");
func("N3-40");
func("N3-41");
func("N3-428");
}
int main()
{
auto func = [](const char* s){ printf("%s\n",s); };
GetInformation(func);
}
这不是真正的错误,从某种意义上说,您不能将函数指针用作参数。你可以。出于模糊性、灵活性和性能原因,不鼓励使用函数指针。请参见 https://jira.sonarsource.com/browse/RSPEC-5205。因此,如果您不关心这些注意事项,您可能想要抑制它。
缺乏灵活性意味着您无法传递额外的上下文(除非使用所谓的“thunks”)。可以通过为用户上下文使用额外的 void*
参数来解决这种缺乏灵活性的问题:
_declspec(dllexport) void GetInformation(
void (add)(const char* pCarName, void* context), void* context)
{
add("N3-988", context);
add("N3-40", context);
add("N3-41", context);
add("N3-428", context);
}
您也可以按照建议使用 std::function
,如果您不认为您的 DLL 将具有 C++ 接口(因此将取决于 C++ 运行时):
_declspec(dllexport) void GetInformation(std::function<void (const char*)> add)
{
add("N3-988");
add("N3-40");
add("N3-41");
add("N3-428");
}
请注意,您不能按照建议使用 template
,因为无法使用 __declspec(dllexport)
从 DLL 导出模板。由于避免间接寻址,模板将具有固定性能,但 DLL 接口意味着您无法避免它。
注意函数作为参数:
void GetInformation(void (add)(const char* pCarName))
由于所谓的衰减:
相当于函数指针参数void GetInformation(void (*add)(const char* pCarName))
建议用一个替换另一个的答案具有误导性,它不会解决任何问题。