函数既指向成员函数的指针又指向const成员函数的指针

时间:2015-07-07 18:34:54

标签: c++ c++11 function-pointers member-function-pointers member-functions

我有以下代码库:

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

当我将指针传递给成员函数(非const)时,这是有效的。 但是,如果我想传递指向const成员函数的指针,则会导致编译错误,我必须复制上述函数才能获得此代码:

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

现在,我可以传递const-member-functions和non-const-member-functions。但是,现在,代码重复,可维护性降低。

有没有办法将这两个函数合并到一个兼容const-member-functions和non-const-member-functions的函数中?

重要提示:我必须将指针函数作为参数(无std :: function)。

编辑:我添加了更多代码。 在函数内部,我构建了一个与成员函数签名匹配的闭包(相同的返回类型和参数)。 此闭包将被存储并在以后用于进行反射(more here

1 个答案:

答案 0 :(得分:5)

您可以编写一个类型特征,根据该特征将告诉您某些MFType上的指针成员函数:

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>
                              > { };

并使用它来确保您只获得其中一个:

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

        // ...
    }
};