【问题标题】:How to replace a function pointer with a template parameter or a std::function?如何用模板参数或 std::function 替换函数指针?
【发布时间】:2021-06-13 15:46:56
【问题描述】:

我在 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".

如何解决?

【问题讨论】:

  • 警告似乎是虚假的,只需压制它。 #pragma warning(suppress: S5205)

标签: c++ sonarlint


【解决方案1】:

这不是一个真正的错误,从某种意义上说,你不能使用函数指针作为参数。你可以。出于晦涩、灵活性和性能原因,不鼓励使用函数指针。见https://jira.sonarsource.com/browse/RSPEC-5205。因此,如果您不关心这些考虑因素,您可能想要抑制它。

缺乏灵活性意味着您不能传递额外的上下文(除非使用所谓的“thunk”)。这种缺乏灵活性可以通过为用户上下文使用额外的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))

由于所谓的decay,相当于函数指针参数:

void GetInformation(void (*add)(const char* pCarName))

建议用另一个替换一个的答案具有误导性,它不会解决任何问题。

【讨论】:

    【解决方案2】:

    错误是一个红鲱鱼。您打错了函数指针语法,仅此而已。你需要

    void (*add)(const char* pCarName)
    

    作为参数类型。 add 则为函数指针,在函数体(add("N3-988"); 等)中使用是合适的。

    【讨论】:

    • 也许更明确地说明void (add)(const char* pCarName)是不能直接传递的函数类型
    • “用模板参数或“std::function”替换这个函数指针。”你没有做任何“建议”
    • @Jarod42:没错。这就是编译器诊断的美妙之处。这有点像我告诉女儿“不要想大象”,然后问她在想什么。
    • @largest_prime_is_463035818:除非您使用模板技巧,否则不会,这可能会炸毁_declspec(dllexport)。后者是我回答中隐藏的考虑因素。
    【解决方案3】:

    大概是这样的

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-09
      • 2019-06-14
      • 1970-01-01
      • 1970-01-01
      • 2012-11-19
      • 2021-12-22
      • 2011-06-13
      • 2013-03-10
      相关资源
      最近更新 更多