【问题标题】:Function taking both pointer to member-function and pointer to const member-function函数同时使用指向成员函数的指针和指向 const 成员函数的指针
【发布时间】:2015-07-07 18:34:54
【问题描述】:

我有以下代码库:

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 成员函数的指针,则会导致编译错误,我必须复制上述函数才能获得此代码:

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 成员函数和非 const 成员函数。但是,现在代码重复了,可维护性降低了。

有没有办法将这两个函数合并成一个同时使用 const-member-functions 和 non-const-member-functions 的函数?

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

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

【问题讨论】:

  • 为什么不简单地template&lt;typename Fun&gt; void register_function(Fun fct)
  • 我用更多代码更新了我的问题。在 lambdas 中,我可以调用 std::bind 或直接在新对象实例上使用成员函数指针。这就是为什么我真的需要访问 ReturnType 和 Params 类型名。
  • 这是你的整个代码库吗?哈哈真的
  • @LightnessRacesinOrbit 完整代码在这里如果你有兴趣github.com/Cylix/cpp_reflection/blob/master/includes/…
  • 你能详细说明“/*做某事*/”吗?

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


【解决方案1】:

您可以编写一个类型特征,基于它会告诉您某些MF 是否是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>
                              > { };

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

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

        // ...
    }
};

【讨论】:

  • @T.C.不知道那个。我想还是要明确检查它是哪个类的成员函数指针。
  • 有趣的答案。但是,我需要访问 ReturnType 和 Params... 类型名。我用更多代码更新了我的问题:我在代码中使用 lambdas,我可以调用 std::bind 或直接在新的 Type 实例上使用函数指针。
  • @SimonNinon 你能用 C++14 吗?可以做auto f = [fct](auto&amp;&amp;... params) { return (Type{}.*fct.second)(std::ref(params)...); };
  • @Barry 告诉我如果我错了,但这意味着在编译时会在调用 lambda 时推断出 Params 类型?问题是 lambda 存储在模板类 function_container 作为 std::function 继承自空类 function_base。这样,function_containers 存储在通用 std::vector 中。然后,在运行时,当用户想要进行反射时,function_base 被动态转换为 function_container。这就是为什么我不认为 Params 类型可以在编译时推断出来。
猜你喜欢
  • 2011-03-04
  • 1970-01-01
  • 2016-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多