【问题标题】:how to avoid code duplication with const and non-const member functions being input into templates如何避免将 const 和非 const 成员函数输入到模板中的代码重复
【发布时间】:2020-02-02 02:38:42
【问题描述】:

当函数被输入到模板中时尝试获取函数签名相当容易,只需执行以下操作:

template <class OutType, class... ArgTypes>
void foo(OutType (*func)(ArgTypes...));

获取非静态成员函数只是稍微复杂一点:

template <class OutType, class MemberOf, class... ArgTypes>
void foo(OutType (MemberOf::*func)(ArgTypes...));

// or

template <class OutType, class MemberOf, class... ArgTypes>
void foo(OutType (MemberOf::*func)(ArgTypes...) const);

但是,当输入法是否为 const 无关紧要时,如何将上面的两个函数声明合二为一呢?

【问题讨论】:

  • 取决于你需要什么template&lt;typename Func&gt; void foo(Func func)是我的第一个goto。
  • @NathanOliver 不幸的是,我需要函数中可用的签名中的所有类型。
  • 我同意 Nathan 的观点,使用 std::invoke 你可以支持的不仅仅是函数指针
  • @MatthewL 那么template &lt;class OutType, class... ArgTypes&gt; void foo(std::function&lt;OutType(ArgTypes...)&gt;);呢?
  • 这似乎可行,但foo(std::function&lt;[whole function signature]&gt;(&amp;bar::do)) 感觉不必要地冗长,尤其是描述性函数/类名

标签: c++ c++11 templates methods constants


【解决方案1】:

不幸的是,const 在非静态成员函数上的存在与否并不是一个可以从它所属的函数类型中单独推断出来的特性。因此,如果你想编写一个foo 模板声明,该声明仅限于接受指向成员的指针(但同时接受const 和非const 成员函数),那么它必须是:

template <class MemberOf, class F>
void foo(F MemberOf::*func);

例如:

#include <type_traits>

template <class MemberOf, class F>
void foo(F MemberOf::*func) {
    static_assert(std::is_same<F, void(int) const>::value);
}

struct S {
    void bar(int) const {}
};

int main() {
    foo(&S::bar);
}

此时您不能推断出F 的参数类型。您将不得不分派给辅助函数。 (但我们不能一次推导出所有类型,同时还要编写一个同时接受const 和非const 的声明。如果这是您唯一能接受的,那么抱歉,这是不可能的。)我们可以像这样:

template <class T>
struct remove_mf_const;

template <class R, class... Args>
struct remove_mf_const<R(Args...)> {
    using type = R(Args...);
};

template <class R, class... Args>
struct remove_mf_const<R(Args...) const> {
    using type = R(Args...);
};

template <bool is_const, class F, class OutType, class MemberOf, class... ArgTypes>
void foo_helper(F func, OutType (MemberOf::*)(ArgTypes...)) {
    // now you have all the types you need
}

template <class MemberOf, class F>
void foo(F MemberOf::*func) {
    static_assert(std::is_function<F>::value, "func must be a pointer to member function");
    using NonConstF = typename remove_mf_const<F>::type;
    constexpr bool is_const = !std::is_same<F, NonConstF>::value;
    foo_helper<is_const>(func, (NonConstF MemberOf::*)nullptr);
}

Coliru link

【讨论】:

    猜你喜欢
    • 2012-01-28
    • 2017-06-19
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多