Function taking both pointer to member-function and pointer to const member-function

陌路散爱 提交于 2020-02-27 23:35:25

问题


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 (non-const). However, if I want to pass a pointer to a const member-function, it results in a compile error and I must duplicate the above function 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 duplicate and maintainability is reduced.

Is there a way to merge these two functions into a function taking both const-member-functions and non-const-member-functions?

Important note: I must really take a pointer function as parameter (no std::function).

Edit: I've added a little bit more code. Inside the functions, I build a closure matching the member function signature (same return types and params). This closure will be stored and used later for making reflection (more here)


回答1:


You could write a type trait, based on which will tell you if some MF is a pointer-to-member function on 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, T C::*> : 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 ensure that you only get one of those:

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)...);
        };

        // ...
    }
};


来源:https://stackoverflow.com/questions/31276652/function-taking-both-pointer-to-member-function-and-pointer-to-const-member-func

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!