【问题标题】:How to pass a function pointer when the pointee has optional parameters?当指针具有可选参数时如何传递函数指针?
【发布时间】:2017-11-08 03:42:36
【问题描述】:

我试图将函数指针作为另一个函数的参数传递,但函数指针本身可能有也可能没有参数(使其与我搜索的其他问题不同)。

代码按原样工作,但我的问题是我试图使用单个函数并传递每个不同的函数指针,但我下面有 3 个不同的函数来传递每个函数指针。我想摆脱 3 个不同的函数定义,因为除了传入的函数指针(基本上,3 个 execute_func() 定义的副本)之外,它们都是相同的。这是我到目前为止所拥有的,但这似乎不对我应该需要三个 execute_func() 调用。

class A { ... };
class B { ... };

class Test {
    private:
        std::function<void()> fp;
        std::function<void(MyA &)> fp;
        std::function<void(MyB &)> fp;
    // ...
};

// Here I create a function pointer for each of my calls.
Test::Test() {
    fp = std::bind(&Test::do_this, this);
    fp_a = std::bind(&Test::do_a, this, std::placeholders::_1);
    fp_b = std::bind(&Test::do_b, this, std::placeholders::_1);
}

// Here my intention was to have only 1 execute_func() call and I would 
// pass in the pointer to the function that I want to call.
Test::test_it()
{
    A a;
    B b;

    execute_func(fp);
    execute_func(fp_a, a);
    execute_func(fp_b, b);
}

// I was hoping to only need one function, but so far
// have needed 3 functions with diff signatures to make it work.
bool Test::execute_func(std::function<void()> fp) {
    // ... more code here before the fp call
    fp();
    // ... them more common code here.
}

bool Test::execute_func(std::function<void(MyA &)> fp, MyA &a) { 
    // ... more common code here 
    fp(a);
    // ... and more common code here
}

bool Test::execute_func(std::function<void(MyB &)> fp, MyB &b) {  
    // ... more common code here 
    fp(b);
    // ... and more common code here.
}

// And of course the execute_func() calls call these members as passed in.
bool Test::do_this() { ... }
bool Test::do_a(MyA &a) { ... }
bool Test::do_b(MyB &b) { ... }

想到我哪里出错了?

【问题讨论】:

  • 您的do_* 函数的返回类型与您传递的std::function 不匹配execute_func。将来,请告诉我们您显示的代码存在什么问题。如果存在构建错误,则包括它们。
  • 你知道完美转发吗?
  • 我已经编辑了请求的信息,希望这更清楚一点。没有构建错误。我只是觉得我做错了,因为我不应该需要 3 个 execute_func() 调用。
  • 你为什么需要execute_func?你可以做fp(); fp_a(a); fp_b(b);
  • 您有三个数据成员(不是成员函数)fp 的声明,它们都具有不同的类型。这行不通。请创建一个minimal reproducible example 并将其与所有实际编译错误一起发布。

标签: c++ c++11 c++14 function-pointers


【解决方案1】:

为此,您可以使用variadic template

template<typename Ret, typename... Args>
bool Test::execute_func(Ret fp(Args&&...), Args&&... args)
{
    // do stuff
    fp(args...);
    // do more stuff
}

我在这里使用的是普通函数指针而不是 std::function,这是 IMO 的巴洛克风格,完全没有必要(这是 C++ 没有 lambda 时的遗物)。但这是相同的想法。

template<typename Ret, typename... Args>
bool Test::execute_func(const std::function<Ret(Args&&...)> &fp, Args&&... args) { }

编辑: Jarod42 points out,您可以使其适用于函数指针 std::function 和任何其他可调用对象,如下所示:

template<typename Func, typename... Args>
bool Test::execute_func(Func &&fp, Args&&... args)
{
    // do stuff
    fp(args...);
    // do more stuff
}

为了使其更加通用,您可以使用std::invoke 调用fp 而不是直接调用它,这还允许fp 成为成员函数或数据成员(实例指针在第一个后续论据)。

template<typename Func, typename... Args>
bool Test::execute_func(Func &&fp, Args&&... args)
{
    // do stuff
    std::invoke(fp, args...);
    // do more stuff
}

前面的例子也可以等价写

template<typename... InvokeArgs>
bool Test::execute_func(InvokeArgs&&... iargs)
{
    // do stuff
    std::invoke(iargs...);
    // do more stuff
}

【讨论】:

  • 您甚至可以使用template&lt;typename F, typename... Args&gt; bool Test::execute_func(F&amp;&amp; fp, Args&amp;&amp;... args)。所以它也适用于std::function 和 OP。
  • std::function 用于类型统一,这是 lambda 根本无法做到的——即使是相同的 lambda 也有不同的类型!例如。 std::map&lt;std::string, std::function&lt;Foo(Bar)&gt; 不能用 lambda 完成。
  • @MSalters 包含在地图中我同意,但在函数参数中,它不是那么有用。如果您希望界面更强大,您还可以将F&amp;&amp; 模板参数限制为可转换为std::function
猜你喜欢
  • 1970-01-01
  • 2018-08-25
  • 1970-01-01
  • 2012-05-03
  • 2018-04-14
  • 1970-01-01
  • 2011-12-23
  • 2012-11-26
  • 2013-10-25
相关资源
最近更新 更多