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