6

长话短说,是否有一种简单/定义的方法来以简化的方式处理函数对象/lambdas 和成员函数?

如果我理解正确,如果我使用 std::mem_fn,我需要将正确类型的对象传递给函数调用,即

Object o;
ftncall std::mem_fun(&Object::function);
ftncall(o);

理想情况下,会有某种方法“附加”o到该函数对象,也许是 a std::weak_ptr,所以我们知道 o 是否被删除。例如,如果有一种方法可以模糊地做这样的事情:

Object o;
ftncall std::mem_fn(&Object::function, o); // Or maybe std::mem_fn<Object>
ftncall();

现在,显然,这不存在(据我所知)。有没有办法以这样的方式包装 std::mem_fn,我不会失去 std::mem_fn 的一般性(和美观性),但可以 'attach' o,并且仍然可以很好地与其他函数类型一起使用,如 std ::功能?理想情况下,我仍然可以像使用operator()std::function 那样使用它。

目前我能想到的最好的解决方案是一个看起来像这样的类:

template<class T>
class MemFunWrapper {
public:
    MemFunWrapper(T* t, std::mem_fun funct) : m_t(t), m_function(funct) {}

    std::mem_fun operator*() { return m_function; }
    T* get() { return m_t; }
private:
    T* m_t;
    std::mem_fun m_function;
}

然后你可以这样使用它:

(*MemFunWrapper)(MemFunWrapper->get(), args...);

但这对我来说似乎很笨拙。此外,我必须为 std::function 创建一个等效类,以便以类似的方式使用它,这似乎很愚蠢,因为我已经可以使用 std::function。理想情况下,我也可以在不知道我是调用成员函数还是常规函数的情况下使用最终产品。我知道我问了很多 - 任何方向都会有帮助。非常感谢!

4

2 回答 2

12

您正在寻找的是 std::bind 而不是 std::mem_fn:

#include <iostream>
#include <functional>

struct Object
{
  void member()
  {
    std::cout << "yay!" << std::endl;
  }
};

int main()
{
  Object o;
  auto fn = std::bind(&Object::member, o);
  fn();
}

FWIW:有一个建议为 std::mem_fn 添加重载,接受该对象以包含在 C++14 中。

于 2013-09-03T04:45:15.723 回答
10

在 C++11 中,我通常发现使用 lambda 最容易做到这一点:

std::shared_ptr<Object> o = std::make_shared<Object>();
auto ftncall = [o](){ if (o) o->function(); }
ftncall();

或者,没有共享生命周期:

Object o;
auto ftncall = [&o](){ o.function(); }
ftncall();

或 ptr 较弱:

std::shared_ptr<Object> o = std::make_shared<Object>();
std::weak_ptr<Object> wo = o;
auto ftncall = [ow](){ if (auto o = wo.lock()) o->function(); }
ftncall();

如果您需要类型擦除,只需将其填充到std::function<void()>.

bindC++11 中的 Lambda 可以完成与不需要依赖库函数的工作相同的工作,而且我个人发现它们更具可读性。

在某些情况下bind可以在 C++11 中做得更好,但在这一点上它们是极端情况(在 C++1y 中,更多的角落也会被切断)。

于 2013-09-03T14:01:36.460 回答