Now, about these overloaded (possibly template) member functions

refl-cpp also allows reflection of member functions, of course. And to distinguish between member types, each MemberInfo has a public typedef, that is equal to one of refl::members::field or refl::members::function (tag types). With function MemberInfo specializations there is a bit more trickery involved to pull everything in place. That is due to the fact that member functions can be either or both overloaded and/or templates.

refl-cpp again uses a different approach to solve the problem of taking a pointer to a member function here. It is based on requiring the user to pass the parameter types they want to call the function pointer later with and looks like this:

That might be a lot to go through at once, so let’s break it down. What is the problem this code is trying to solve? Imagine having a type A with two overloads of a function — f(int) and f(const std::string&). When trying to take a pointer to the function f (by &A::f), how is the compiler going to know how to resolve that expression to a specific definition?

What refl-cpp does is aid the compiler in deducing the proper overload in the same way it does when directly invoking the function — by passing the &A::f to another function as a parameter, which is one of the cases when the c can be concrete type can be resolved (when the context it is passed in has a specified type). resolve has no definition, just a prototype — that is simply because it is never needed. It just acts as a hint to the compiler. The nice thing about passing the functional arguments (resulting from std::declval) is that all the usual argument conversions apply, meaning that one can use MemberInfo<?>::pointer<int> and get a pointer of type void(*)(long) as a result (which would be fine to invoke with an int).