带有ref_qualified成员函数的std :: mem_fn

Aru*_*nmu 5 c++ c++11

我们有什么方法可以使用ref合格的成员函数std::mem_fn吗?

以下代码无法编译:

class DeadPool {
public:
  void jump() & {
    std::cout << "Did not jump\n";
  }

  void jump() && {
    std::cout << "Jumped from helicopter\n";
  }
};

int main() {
  DeadPool dp1;
  //auto cobj = std::mem_fn(&DeadPool::jump); // Won't compile
  //cobj(dp1);
  //cobj(DeadPool());
  using Func = void (DeadPool::*) () &; // lvalue ref qualifier explicitly provided
  Func fp = &DeadPool::jump; // This works, as expected
  (std::move(dp1).*fp)();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

错误信息:

mem_fn_ex.cc:18:15:错误:没有用于调用'mem_fn'的匹配函数
auto cobj = std :: mem_fn(&DeadPool :: jump); //将无法编译^ ~~~~~~~~~~/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/functional:1233:1:注意:候选模板被忽略:couldn推断模板参数'_Rp'mem_fn(_Rp _Tp ::*__pm)^ mem_fn_ex.cc:23:18:错误:指向成员的函数类型'Func'(又名'void(DeadPool ::*)() &')只能在左值上调用(std :: move(dp1).*fp)(); ~~~~~~~~~~~~~~ ^

编译器:在Clang(3.4)和g ++(5.3)上

我以为我可以利用这样一个事实,即在std::_Mem_fn类实现中调用rvalue对象,如下所示:

return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
Run Code Online (Sandbox Code Playgroud)

这可以很好地调用特定于rvalue的成员函数this,但由于签名在编译时是不同的,所以它不能这样做.

Bar*_*rry 4

问题是您将重载函数传递到函数模板中 -mem_fn()无法推断出您想要的函数 jump()。您需要通过强制转换来传递特定的一个:

auto cobj = std::mem_fn(static_cast<void (DeadPool::*)() &>(&DeadPool::jump));
cobj(dp1);        // ok
cobj(DeadPool()); // error
Run Code Online (Sandbox Code Playgroud)

然而,由于冗长(需要输入很多内容)和限制(出于某种原因,您有&- 和&&- 限定的重载,但只能使用一个?),这确实是一个令人不满意的解决方案。最好在这里使用通用 lambda:

auto jump = [](auto&& pool){ std::forward<decltype(pool)>(pool).jump(); };
jump(dp1);         // ok: Did not jump
jump(DeadPool());  // ok: Jumped from helicopter
Run Code Online (Sandbox Code Playgroud)