Is it possible to specialize a function with member function pointers with convenient syntax for calling?

Take a look at this non-compiling snippet:

struct Object { template <RETURN (OBJECT::*MEMFN)(PARAMETERS...), typename RETURN, typename OBJECT, typename ...PARAMETERS> void call() { } }; struct Foo { void fn(); }; int main() { Object o; o.call<&Foo::fn>(); } 

Basically, I want to get a function ( Object::call ) that specializes in any member function pointers, with convenient syntax for calling.

The closest solution I found is that is very ugly:

 struct Object { }; template <typename MEMFNTYPE, MEMFNTYPE MEMFN> struct Caller; template <typename RETURN, typename OBJECT, typename ...PARAMETERS, RETURN (OBJECT::*MEMFN)(PARAMETERS...)> struct Caller<RETURN (OBJECT::*)(PARAMETERS...), MEMFN> { Object *object; Caller(Object &o) : object(&o) { } void call() { // I have the necessary information here: the member function pointer as template parameter, and a pointer to Object } }; struct Foo { void fn(); }; int main() { Object o; Caller<decltype(&Foo::fn), &Foo::fn>(o).call(); } 

Is there a better solution to this problem?

(The reason that I am trying to do this is that I would like to create wrapper functions ( call ) for other member functions)


Kerrek SB suggested using auto , I tried this:

 struct Object { template <auto MEMFN> void call(); template <auto MEMFN, typename RETURN, typename OBJECT, typename ...PARAMETERS> void call<RETURN (OBJECT::*MEMFN)(PARAMETERS...)>() { } }; struct Foo { void fn(); }; int main() { Object o; o.call<&Foo::fn>(); } 

However, this does not compile (I need to add MEMFN differently to the list of template parameters (instead of auto MEMFN ?):

 t2.cpp:6:7: error: parse error in template argument list void call<RETURN (OBJECT::*MEMFN)(PARAMETERS...)>() { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ t2.cpp:6:52: error: non-class, non-variable partial specialization 'call<<expression error> >' is not allowed void call<RETURN (OBJECT::*MEMFN)(PARAMETERS...)>() { 
+3
c ++
source share
1 answer

As suggested in the comments, if you are making C ++ 17 decisions, then auto is your friend. And so <type_traits> and if constexpr :

 #include <type_traits> #include <iostream> struct Object { template <auto MEMFN> void call() { if constexpr (std::is_member_function_pointer_v<decltype(MEMFN)>) std::cout << "Is member\n"; } }; struct Foo { void fn(); }; int main() { Object o; o.call<&Foo::fn>(); } 

The body of the function will only generate code that treats the parameter as a pointer to a member function, if the type bar says that it really is. Specialization is not required.

+2
source share

All Articles