Std :: mem_fn with ref_qualified member functions

Is there any way we can use reflective member functions with std::mem_fn ?

The code below does not 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: there is no corresponding function to call in mem_fn

auto cobj = std :: mem_fn (& DeadPool :: jump); // Do Not Compile ^ ~~~~~~~~~~ / Library / Developer / CommandLineTools / usr / bin /../include/c ++/v1/ functional: 1233: 1: note: the candidate template is ignored: cannot print the argument of the template '_Rp' mem_fn (_Rp _Tp :: * __pm) ^ mem_fn_ex.cc:23:18: error: pointer to element Function type "Func" (aka 'void (DeadPool :: *) () &') can only be called on lvalue (std :: move (dp1). * fp) (); ~~~~~~~~~~~~~~ ^ ^

Compiler: for both Clang (3.4) and g ++ (5.3)

I thought I could use the fact that in the implementation of the std::_Mem_fn the rvalue object is called, as shown below:

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

This could very well call a member function specific to rvalue this , but since the signatures are different at compile time, it cannot do this.

+5
source share
1 answer

The problem is that you pass the overloaded function to the function template - mem_fn() cannot determine which jump() you want. You will need to pass a specific version:

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

However, this is a really unsatisfactory solution due to both verbosity (which is LOT for input) and restrictions (do you have & - and && -computable overloads for any reason, but can you use only one?). Better use a common lambda here:

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

All Articles