A function that takes both a pointer to a member function and a pointer to a constant member function

I have the following code base:

template <typename Type> class SomeClass { public: template <typename ReturnType, typename... Params> void register_function(const std::pair<std::string, ReturnType (Type::*)(Params...)> fct) { auto f = [fct](Params... params) -> ReturnType { return (Type().*fct.second)(std::ref(params)...); } // ... } }; 

This works when I pass a pointer to a member function (not a constant). However, if I want to pass a pointer to a constant member function, this will lead to a compilation error, and I have to duplicate the above function in order to get this code:

 template <typename Type> class SomeClass { public: template <typename ReturnType, typename... Params> void register_function(const std::pair<std::string, ReturnType (Type::*)(Params...)> fct) { auto f = [fct](Params... params) -> ReturnType { return (Type().*fct.second)(std::ref(params)...); } // ... } template <typename ReturnType, typename... Params> void register_function(const std::pair<std::string, ReturnType (Type::*)(Params...) const> fct) { auto f = [fct](Params... params) -> ReturnType { return (Type().*fct.second)(std::ref(params)...); } // ... } }; 

Now I can pass both const-member functions and non-const-member functions. But now the code is duplicated, and maintainability is reduced.

Is there a way to combine these two functions into a function that accepts both const-member-functions and non-const-member-functions?

Important note: I really have to use the pointer function as a parameter (no std :: function).

Edit: I added a bit more code. Inside the functions, I build a closure corresponding to the signature of the member function (the same types of returned parameters and parameters). This closure will be saved and used later for reflection ( more details here )

+5
source share
1 answer

You can write the nature of the type, on the basis of which it will be indicated whether some MF function is a member function of a pointer to Type :

 template <typename C, typename T> struct is_pointer_to_member_helper : std::false_type { }; template <typename C, typename T> struct is_pointer_to_member_helper<C, TC::*> : std::is_function<T> { }; template <typename C, typename T> struct is_pointer_to_member : is_pointer_to_member_helper<C, std::remove_cv_t<T> > { }; 

And use it to make sure that you get only one of them:

 template <typename Type> class SomeClass { public: template <typename MF> std::enable_if_t<is_pointer_to_member<Type, MF>::value> register_function(const std::pair<std::string, MF> fct) { auto f = [fct](auto&&... params) { return (Type{}.*fct.second)(std::forward<decltype(params)>(params)...); }; // ... } }; 
+5
source

All Articles