I often find myself wishing there was a generalized way of calling functions and function-like “things”.

Functors are obviously quite function-like. Member function pointers can be treated like function where the object pointer as just another parameter. Member object pointers can be treated like a function which retrieves a member from a pointed object.

Now with the new c++11 standard, it is possible to do this quite easily!

#include <type_traits> #include <utility> // functions, functors, lambdas, etc. template< class F, class... Args, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type, class = typename std::enable_if<!std::is_member_object_pointer<F>::value>::type > auto eval(F&& f, Args&&... args) -> decltype(f(std::forward<Args>(args)...)) { return f(std::forward<Args>(args)...); } // const member function template<class R, class C, class... Args> auto eval(R(C::*f)() const, const C& c, Args&&... args) -> R { return (c.*f)(std::forward<Args>(args)...); } template<class R, class C, class... Args> auto eval(R(C::*f)() const, C& c, Args&&... args) -> R { return (c.*f)(std::forward<Args>(args)...); } // non-const member function template<class R, class C, class... Args> auto eval(R(C::*f)(), C& c, Args&&... args) -> R { return (c.*f)(std::forward<Args>(args)...); } // member object template<class R, class C> auto eval(R(C::*m), const C& c) -> const R& { return c.*m; } template<class R, class C> auto eval(R(C::*m), C& c) -> R& { return c.*m; }

The first overload of eval covers almost every single case. Furthermore, note the use of universal references and forwarding which automatically handles const and reference qualifiers.

The next three overloads handle const and non-const member function pointers. Additional parameters of C& are added as if they were parameters of the original functions.

Member object pointers are then treated as functions which take a reference to an object then return a reference to its member.

The use of std::enable_if prevents the first overload from greedily instantiating for member function pointers.

Now to show it in action:

#include <iostream> struct Bloop { int a = 10; int operator()(){return a;} int operator()(int n){return a+n;} int triple(){return a*3;} }; int add_one(int n) { return n+1; } int main() { Bloop bloop; // free function std::cout << eval(add_one,0) << "

"; // lambda function std::cout << eval([](int n){return n+1;},1) << "

"; // functor std::cout << eval(bloop) << "

"; std::cout << eval(bloop,4) << "

"; // member function std::cout << eval(&Bloop::triple,bloop) << "

"; // member object eval(&Bloop::a,&bloop)++; // increment a by reference std::cout << eval(&Bloop::a,bloop) << "

"; return 0; }

Which gives the expected output:

1 2 10 14 30 11

Note: Be careful with pointers to overloaded functions, the compiler will not be able to determine which overload to use. You will need to either explicitly cast to a function pointer or std::function object with the desired type.

Edit: Thank you to STL for pointing out member object pointers should return references, not values.

Edit2: Thanks to Aaron McDaid for pointing out a few more mistakes.