在C ++ 11中使用std :: function / mem_fn和成员函数

时间:2013-09-03 04:41:38

标签: c++ c++11 lambda metaprogramming function-pointers

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

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

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

理想情况下,有一些方法可以将o'附加'到该函数对象,可能是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的通用性(和好看性),但可以“附加”o,并且仍然可以很好地与其他人一起玩函数类型,如std :: function?理想情况下,我仍然可以像使用std :: function一样使用operator()

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

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了。理想情况下,我也可以在不知道我是否正在调用成员函数或常规函数的情况下使用最终产品。我知道我问了很多 - 任何方向都会有所帮助。非常感谢!

2 个答案:

答案 0 :(得分:10)

你要找的是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:有一个proposal用于向std :: mem_fn添加一个重载,接受包含在C ++ 14中的对象。

答案 1 :(得分:9)

在C ++ 11中,我通常发现使用lambdas最简单:

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

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

C ++ 11中的Lambdas可以完成与bind相同的工作,而不必依赖库函数来完成它,我个人觉得它们更具可读性。

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