具有ref_qualified成员函数的{std :: mem_fn

时间:2016-07-23 15:38:53

标签: c++ c++11

我们是否可以通过std::mem_fn使用ref限定成员函数?

以下代码无法编译:

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;
}

错误讯息:

  

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

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

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

return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);

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

1 个答案:

答案 0 :(得分:4)

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

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

然而,这是一个非常不令人满意的解决方案,因为冗长(这是一个很难打字)和限制(你有& - 和&& - 合格的重载有一个原因,但你可以只用一个?)。最好在这里使用通用lambda:

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