【问题标题】:How can I make a C++ member function by binding the arguments of another member function?如何通过绑定另一个成员函数的参数来创建 C++ 成员函数?
【发布时间】:2017-12-27 14:45:47
【问题描述】:

我在“即时”创建一个指向成员函数 (PTMF) 类型的变量时遇到问题(即,通过 std::bind 固定现有成员函数的一些参数)。我的问题是 C++11 或后 C++11 标准是否有可能。

Preambula:我有一个类,它存储从 PTMF 初始化的 std::functions 的静态 const 数组,以下称为“处理程序”。最初,它们是具有名称和实现的常规成员函数,因此我从未使用过 C++11 和 std::function。然后,我决定它们中的许多几乎相似,并决定使用“生成器函数”生成它们。我想避免使用模板来生成,因为这些几乎相似的处理程序的数量将在未来急剧增加(大约 200 多个),而模板化只会导致代码膨胀。

如果有问题的 PTMF 是静态的,那么通过 std::bind 生成处理程序不会有任何问题。一个简化的例子:

#include <iostream>
#include <functional>


using namespace std;


struct A {
    typedef function<void(int)> HandlerFn;

    static void parametrized_handler(int i, const char *param) {
        cout << "parametrized handler: " << param << endl;
    }

    static void handler(int i) { cout << "handler 1" << endl; }

    int mm;
};

static const A::HandlerFn handler2 = [](int) { cout << "handler 2" << endl; };

static const A::HandlerFn handler3 = bind(A::parametrized_handler,
                                          placeholders::_1,
                                          "test_param");


int main()
{
    A::handler(42);
    handler2(42);
    handler3(42);

    return 0;
}

输出:

$ ./a.out 
handler 1
handler 2
parametrized handler: test_param

当我转向非静态成员函数时,问题就出现了。 std::bind 无法生成像 PTMF 一样的函数对象。我知道我可以将一个真实对象作为第一个参数传递给 bind 并获得一个工作函数,但这不是我想要的:当我初始化一个静态 const 数组时,根本没有对象,并且 bind 的结果将无论如何都充当常规的非成员函数。

非静态成员函数的预期实现(带有虚构的 std::bind_mem 绑定器):

#include <iostream>
#include <functional>


using namespace std;

struct A;


struct A {
    typedef function<void(int)> HandlerFn;

    void parametrized_handler(int i, const char *param) {
        mm;
        cout << "parametrized handler: " << param << endl;
    }

    void handler(int i) const { mm; cout << "handler 1" << endl; }

    const HandlerFn handler2 = [this](int i) { mm; cout << "handler 2" << endl; };

    int mm;
};


// An imaginary PTMF binder
// static const A::HandlerFn handler3 = bind_mem(A::parametrized_handler,
//                                               placeholders::_1,
//                                               "test_param");



int main()
{
    A a;

    (a.handler)(42);
    (a.handler2)(42);
    //(a.handler3)(42);

    return 0;
}

输出:

$ ./a.out 
handler 1
handler 2

那么有没有办法实现 PTMF 参数绑定?

【问题讨论】:

  • 使用..*,你不能。 -&gt; 会很笨拙,但是 -&gt;* 呢?您可以将您的函数包装在您自己的类中,并为此重载operator -&gt;*
  • @Slava:那么,您基本上是在建议将所有处理程序设为静态。这应该可行,但是由于它使我的整个处理程序系统离开了指向成员的世界,因此除了制作自己的类函数类(@Quentin)或使用模板之外,我仍然将其作为最后的解决方案.我仍然希望有一个允许我创建 PTMF 的解决方案;除了提供的基本示例之外,我还需要生成指向成员的指针。

标签: c++ c++11 std-function stdbind


【解决方案1】:

要绑定指向非静态成员函数的指针,您需要一个对象。

#include<functional>

struct A {
    typedef std::function<void(int)> HandlerFn;
    void mem(int);
    void static static_mem(int);
};

void foo() {
    A a;
    A::HandlerFn h1 = A::static_mem;
    //This captures a by ref
    A::HandlerFn h2 = std::bind(&A::mem, std::ref(a), std::placeholders::_1);
    //This captures a by copy
    A::HandlerFn h3 = std::bind(&A::mem, a, std::placeholders::_1);
    //Change to =a for copy
    A::HandlerFn h4 = [&a](int i){
        a.mem(i);
    };
    h1(34);
    h2(42);    
}

链接:https://godbolt.org/g/Mddexq

【讨论】:

  • 这令人失望,因为从逻辑上讲,绑定不需要对象。 =( 好的,谢谢。
  • @cheater。没有对象就不能调用成员函数。如果类中没有状态,考虑移除类,只使用命名空间对相关函数进行分组。
  • 我说的不是调用处理程序,而是声明它们。对于状态:不幸的是,该类有一个状态(在我的示例中通过成员“mm”模拟)。
猜你喜欢
  • 2016-09-11
  • 2013-07-10
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多