Is there any way by which we can make use of ref qualified member functions with std::mem_fn ?
The below code fails to compile:
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;
}
Error message:
mem_fn_ex.cc:18:15: error: no matching function for call to 'mem_fn'
auto cobj = std::mem_fn(&DeadPool::jump); // Won't compile ^~~~~~~~~~~ /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/functional:1233:1: note: candidate template ignored: couldn't infer template argument '_Rp' mem_fn(_Rp _Tp::* __pm) ^ mem_fn_ex.cc:23:18: error: pointer-to-member function type 'Func' (aka 'void (DeadPool::*)() &') can only be called on an lvalue (std::move(dp1).*fp)(); ~~~~~~~~~~~~~~^
Compiler: On both Clang(3.4) and g++ (5.3)
I thought I could make use of the fact that, in std::_Mem_fn class implementation an rvalue object is invoked like below:
return (std::move(__object).*__pmf)(std::forward<_Args>(__args)...);
This could have very well invoked the member function specific for rvalue this, but since the signatures are different at compile time, it cannot do that.
The problem is that you're passing an overloaded function into a function template - mem_fn() can't deduce which jump() you want. You would need to pass a specific one with a cast:
auto cobj = std::mem_fn(static_cast<void (DeadPool::*)() &>(&DeadPool::jump));
cobj(dp1); // ok
cobj(DeadPool()); // error
However, that's a really unsatisfying solution due to both the verbosity (that's a LOT to type) and the limitations (you have &- and &&-qualified overloads for a reason, but you can only use one?). Better to use a generic lambda here:
auto jump = [](auto&& pool){ std::forward<decltype(pool)>(pool).jump(); };
jump(dp1); // ok: Did not jump
jump(DeadPool()); // ok: Jumped from helicopter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With